Flutter上拉刷新和下拉加载

2019-04-21  本文已影响0人  DASH_1024

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;
  }

}
上一篇下一篇

猜你喜欢

热点阅读