web-dev-qa-db-ja.com

Flutter:ListViewがスクロールできない、バウンスしない

次の例があります(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に追加しても効果がありません。

助けてくれてありがとう:)

12
Renato Stauffer

ListViewで常にスクロールを有効にするには、AlwaysScrollableScrollPhysicsクラスを使用して、元のスクロールのフィジックスをラップすることができます。詳細 こちら 。必要に応じて、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,
          ),
        ]
    );
  }
}
11
Fabio Veronese

このソリューションは、CustomScrollViewがなければより良いと思います。 NotificationListenerを使用して、ListViewをラップするだけです。

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

私はそれをテストしました、バウンスは効果的です

0
ken

AlwaysScrollableScrollPhysicsを追加するだけです

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

ビューポートよりもコンテンツの高さが低いリストでオフセットを追跡する方法を見つけました。次のように、build()メソッドでNotificationListenerCustomScrollViewと一緒に使用します。

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のみ(または「より良い」(よりエレガント)な)解決策がない限り、これを答えとして受け入れます。

0
Renato Stauffer