Flutter学习笔记

Flutter-监听滚动事件

2020-04-19  本文已影响0人  WinJayQ

对于滚动的视图,我们经常需要监听它的一些滚动事件,在监听到的时候去做对应的一些事情。
比如视图滚动到底部时,我们可能希望做上拉加载更多;
比如滚动到一定位置时显示一个回到顶部的按钮,点击回到顶部的按钮,回到顶部;
比如监听滚动什么时候开始,什么时候结束;
在Flutter中监听滚动相关的内容由两部分组成:ScrollController和ScrollNotification。

1. ScrollController

在Flutter中,Widget并不是最终渲染到屏幕上的元素(真正渲染的是RenderObject),因此通常这种监听事件以及相关的信息并不能直接从Widget中获取,而是必须通过对应的Widget的Controller来实现。

ListView、GridView的组件控制器是ScrollController,我们可以通过它来获取视图的滚动信息,并且可以调用里面的方法来更新视图的滚动位置。

另外,通常情况下,我们会根据滚动的位置来改变一些Widget的状态信息,所以ScrollController通常会和StatefulWidget一起来使用,并且会在其中控制它的初始化、监听、销毁等事件。

我们来做一个案例,当滚动到1000位置的时候,显示一个回到顶部的按钮:

class MyHomePage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _MyHomePageState();
  }
}

class _MyHomePageState extends State<MyHomePage> {

  ScrollController _controller;
  bool _isShowTop = false;

  @override
  void initState() {
    //初始化ScrollController
    _controller = ScrollController();

    //监听滚动
    _controller.addListener((){
      var tempShowTop = _controller.offset >= 1000;
      if(tempShowTop != _isShowTop){
        setState(() {
          _isShowTop = tempShowTop;
        });
      }
    });

    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("ListView展示"),
      ),
      body: ListView.builder(
        itemCount: 100,
        itemExtent: 60,
        controller: _controller,
        itemBuilder: (BuildContext context,int index){
          return ListTile(
            title: Text("item $index"),
          );
        },
      ),
      floatingActionButton: !_isShowTop?null:FloatingActionButton(
        child: Icon(Icons.arrow_upward),
        onPressed: (){
          _controller.animateTo(0, duration: Duration(milliseconds: 1000), curve: Curves.ease);
        },
      ),
    );
  }
}
image.png

2. NotificationListener

如果我们希望监听什么时候开始滚动,什么时候结束滚动,这个时候我们可以通过NotificationListener。

案例: 列表滚动, 并且在中间显示滚动进度

class MyHomeNotificationDemo extends StatefulWidget {
  @override
  _MyHomeNotificationDemoState createState() => _MyHomeNotificationDemoState();
}

class _MyHomeNotificationDemoState extends State<MyHomeNotificationDemo> {

  int _progress = 0;

  @override
  Widget build(BuildContext context) {
    return NotificationListener(
      onNotification: (ScrollNotification notification){
        //1.监听事件的类型
        if(notification is ScrollStartNotification){
          print("开始滚动...");
        }else if(notification is ScrollUpdateNotification){
          //当前滚动的位置和总长度
          final currentPixel = notification.metrics.pixels;
          final totalPixel = notification.metrics.maxScrollExtent;
          double progress = currentPixel/totalPixel;
          setState(() {
            _progress = (progress*100).toInt();
          });
          print("正在滚动:${notification.metrics.pixels} - ${notification.metrics.maxScrollExtent}");
        }else if(notification is ScrollEndNotification){
          print("滚动结束....");
        }
        return false;
      },
      child: Stack(
        alignment: Alignment(.9,.9),
        children: <Widget>[
          ListView.builder(
            itemCount: 100,
            itemExtent: 80,
            itemBuilder: (BuildContext context,int index){
              return ListTile(title: Text("item $index"),);
            },
          ),
          CircleAvatar(
            radius: 30,
            child: Text("$_progress%"),
            backgroundColor: Colors.black54,
          ),
        ],
      ),
    );
  }
}
image.png

学习内容来自Flutter从入门到实战

上一篇下一篇

猜你喜欢

热点阅读