Flutter:ListView不可滚动,不会弹跳

时间:2018-01-03 17:04:18

标签: listview dart scrollview flutter

我有以下示例(在iPhone X,iOS 11上测试):

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  @override
  Widget build(BuildContext context) {
    return new ListView(
      children: <Widget>[
        new Container(
          height: 40.0,
          color: Colors.blue,
        ),
        new Container(
          height: 40.0,
          color: Colors.red,
        ),
        new Container(
          height: 40.0,
          color: Colors.green,
        ),
      ]
    );
  }

}

在这种情况下,ListView的行为与预期的一样。我可以滚动到视口之外,ListView会再次反弹(典型的iOS行为)。但是当我添加ScrollController来跟踪偏移量时,滚动的行为会发生变化:

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  ScrollController _controller = new ScrollController();

  @override
  Widget build(BuildContext context) {
    return new ListView(
      controller: _controller,
      children: <Widget>[
        new Container(
          height: 40.0,
          color: Colors.blue,
        ),
        new Container(
          height: 40.0,
          color: Colors.red,
        ),
        new Container(
          height: 40.0,
          color: Colors.green,
        ),
      ]
    );
  }
}

在这种情况下,滚动不再可能。为什么当我添加ScrollController时,滚动不再可能?将physics: new BouncingScrollPhysics(),添加到ListView也无济于事。

感谢您的帮助:)

6 个答案:

答案 0 :(得分:4)

要始终在ListView上启用滚动,您可以使用AlwaysScrollableScrollPhysics类包装所需的原始滚动体。更多细节here。如果需要,您可以指定parent或依赖默认值。

以下是添加选项的示例:

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  ScrollController _controller = new ScrollController();

  @override
  Widget build(BuildContext context) {
    return new ListView(
        physics: const AlwaysScrollableScrollPhysics(), // new
        controller: _controller,
        children: <Widget>[
          new Container(
            height: 40.0,
            color: Colors.blue,
          ),
          new Container(
            height: 40.0,
            color: Colors.red,
          ),
          new Container(
            height: 40.0,
            color: Colors.green,
          ),
        ]
    );
  }
}

答案 1 :(得分:3)

使用AlwaysScrollableScrollPhysics创建滚动物理学,始终让用户滚动。

对于具有弹跳效果的滚动,只需向滚动条提供物理:BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics)。即使没有内容溢出,它也将始终可滚动

const BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics())

这里是完整的例子

ListView(
  padding: EdgeInsets.all(8.0),
  physics: const BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics()),
  children: _listData.map((i) {
    return ListTile(
      title: Text("Item $i"),
    );
  }).toList(),
);

enter image description here

答案 2 :(得分:2)

只需添加AlwaysScrollableScrollPhysics

ListView(
        physics: const AlwaysScrollableScrollPhysics(),
        children :  [...]
}

答案 3 :(得分:0)

我找到了一个解决方案,如何使用内容高度小于视口的列表来跟踪偏移量。在NotificationListener方法中使用CustomScrollViewbuild(),如下所示:

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  ScrollController _controller = new ScrollController();

  @override
  Widget build(BuildContext context) {
    return new NotificationListener(
      onNotification: _handleScrollPosition,
        child: new CustomScrollView(
            slivers: [
              new SliverList(
                  delegate: new SliverChildListDelegate([
                    new Container(
                      height: 40.0,
                      color: Colors.blue,
                    ),
                    new Container(
                      height: 40.0,
                      color: Colors.red,
                    ),
                    new Container(
                      height: 40.0,
                      color: Colors.green,
                    ),
                  ])
              )
            ]
        )
    );
  }

  bool _handleScrollPosition(ScrollNotification notification) {
    print(notification.metrics.pixels);
    return true;
  }
}

只要没有只有ScrollController(或更好的&#34;(更优雅))解决方案的解决方案,我会接受这个作为答案。

答案 4 :(得分:0)

我认为如果没有CustomScrollView,此解决方案会更好。只需使用NotificationListener包装ListView。

  Widget noti = new NotificationListener(
    child:listView,
    onNotification: (ScrollNotification note){
      print(note.metrics.pixels.toInt());
    },
  );

我已经测试过,弹跳有效

答案 5 :(得分:0)

**

使用容器高度进行滚动,也可以使用 物理:AlwaysScrollableScrollPhysics(), 控制器:控制器,

**

implementation 'com.google.android.material:material:1.2.1'