美文网首页
Flutter上拉刷新和下拉加载

Flutter上拉刷新和下拉加载

作者: DASH_1024 | 来源:发表于2019-04-21 15:00 被阅读0次

    Flutter中使用ListView时常常会用到上拉刷新和下拉加载功能,上拉刷新比较好实现,直接在ListView外面套一层RefreshIndicator,再实现RefreshIndicator就可以了。下拉加载就没有现成的可以用了,需要我们自己来实现。本文主要对Flutter中上拉刷新和下拉加载功能封装为一个简单的类RefreshListView。

    主要可以分为三个步骤来实现:
    1.上拉刷新,如前面所说用RefreshIndicator来实现 ;
    2.下拉加载,通过ScrollController监听是否滑动到底部,在滑到底部时添加自定义的动画效果;
    3.没有更多数据的提示,也主要通过监听滑到底部时,检查是否有更多数据,没有则显示自定义的提示信息

    下面我们结合代码来进行初步实现

    上拉刷新

        RefreshIndicator refreshIndicator = RefreshIndicator(
          onRefresh: () => onRefresh(),
          child: listView,
        );
    

    实现RefreshIndicator中的onRefresh方法,这里我们自定义了一个onRefresh()接口,外层调用时通过此方法进行数据的更新。child为一个listView,如下:

        ListView listView = ListView.builder(
          controller: scrollController,
          itemCount: length + 1,
          shrinkWrap: true,
          itemBuilder: (context, index) {
            return _generateItem(context, index);
          }
        );
    

    下拉加载

        ScrollController scrollController = ScrollController();
        scrollController.addListener(() {
          if(scrollController.position.pixels == scrollController.position.maxScrollExtent) {
            print('arrive end: hasMore = $hasMore');
            if(hasMore) {
              onLoad();
            }
          }
        });
    

    在listView上添加一个scrollController,然后添加一个滑动监听,当listView滑动到底部时,这里有一个hasMore变量来判断是否还有更多数据,如果还有就加载更多。其中加载跟多的方法onLoad也是一个可供外层调用的接口。

    没有更多数据的提示

      Widget _generateItem(BuildContext context, int index) {
        if(index < length) {
          return buildItem(index);
        } else {
          if(hasMore) {
            return _buildLoadMoreView();
          } else {
            return _buildNoMoreView();
          }
        }
      }
    

    在设置listView的itemCount时,我们设置的值为list的length加1,为的就是当listView滑到底部时显示更多数据的动画或者没有数据的提示。当hasMore为false时,就显示所有数据加载完成的提示信息。_buildNoMoreView代码如下:

      Widget _buildNoMoreView() {
        Container container = Container(
          height: 40,
          child: Center(
              child: Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Text(
                    '- ',
                    style: TextStyle(
                        fontSize: Appearance.fontSize.title2,
                        color: Appearance.color.foot
                    ),
                  ),
                  Text(
                    '我也是有底线的',
                    style: TextStyle(
                        fontSize: Appearance.fontSize.title2,
                        color: Appearance.color.foot
                    ),
                  ),
                  Text(
                    ' -',
                    style: TextStyle(
                        fontSize: Appearance.fontSize.title2,
                        color: Appearance.color.foot
                    ),
                  ),
                ],
              )
          ),
        );
    
        return container;
      }
    

    这里只是象征性地给出了一种示例,你也可以自定义自己想要的提示信息显示效果。

    最后,完整代码如下:

    import 'package:flutter/material.dart';
    import 'package:inee_flutter/profiles/appearance.dart';
    
    typedef LoadMore = void Function();
    typedef Refresh = Future Function();
    typedef BuildItem = Widget Function(int);
    
    class RefreshListView extends StatelessWidget {
    
      final int length;
      final LoadMore onLoad;
      final Refresh onRefresh;
      final BuildItem buildItem;
      final bool hasMore;
    
      RefreshListView({
        Key key,
        this.length,
        this.onLoad,
        this.onRefresh,
        this.buildItem,
        this.hasMore = true,
      }) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        if(length == 0) {
          return Container();
        }
    
        ScrollController scrollController = ScrollController();
        scrollController.addListener(() {
          if(scrollController.position.pixels == scrollController.position.maxScrollExtent) {
            print('arrive end: hasMore = $hasMore');
            if(hasMore) {
              onLoad();
            }
          }
        });
    
        ListView listView = ListView.builder(
          controller: scrollController,
          itemCount: length + 1,
          shrinkWrap: true,
          itemBuilder: (context, index) {
            return _generateItem(context, index);
          }
        );
    
        RefreshIndicator refreshIndicator = RefreshIndicator(
          onRefresh: () => onRefresh(),
          child: listView,
        );
    
        return refreshIndicator;
      }
    
      Widget _generateItem(BuildContext context, int index) {
        if(index < length) {
          return buildItem(index);
        } else {
          if(hasMore) {
            return _buildLoadMoreView();
          } else {
            return _buildNoMoreView();
          }
        }
      }
    
      Widget _buildLoadMoreView() {
        Container container = Container(
          child: Padding(
            padding: EdgeInsets.symmetric(vertical: 5),
            child: Center(
              child: Image.asset("assets/loadingAnimation.gif", width: 29, height: 38),
            ),
          ),
        );
    
        return container;
      }
    
      Widget _buildNoMoreView() {
        Container container = Container(
          height: 40,
          child: Center(
              child: Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Text(
                    '- ',
                    style: TextStyle(
                        fontSize: Appearance.fontSize.title2,
                        color: Appearance.color.foot
                    ),
                  ),
                  Text(
                    '我也是有底线的',
                    style: TextStyle(
                        fontSize: Appearance.fontSize.title2,
                        color: Appearance.color.foot
                    ),
                  ),
                  Text(
                    ' -',
                    style: TextStyle(
                        fontSize: Appearance.fontSize.title2,
                        color: Appearance.color.foot
                    ),
                  ),
                ],
              )
          ),
        );
    
        return container;
      }
    
    }
    

    相关文章

      网友评论

          本文标题:Flutter上拉刷新和下拉加载

          本文链接:https://www.haomeiwen.com/subject/afbdgqtx.html