Flutter实现下拉刷新和上拉加载更多

本文实例为大家分享了Flutter实现下拉刷新和上拉加载更多的具体代码,供大家参考,具体内容如下

效果

下拉刷新

如果实现下拉刷新,必须借助RefreshIndicator,在listview外面包裹一层RefreshIndicator,然后在RefreshIndicator里面实现onRefresh方法。

body: movieList.length == 0
          ? new Center(child: new CircularProgressIndicator())
          : new RefreshIndicator(
              color: const Color(0xFF4483f6),
              //下拉刷新
              child: ListView.builder(
                itemCount: movieList.length + 1,
                itemBuilder: (context, index) {
                  if (index == movieList.length) {
                    return _buildProgressMoreIndicator();
                  } else {
                    return renderRow(index, context);
                  }
                },
                controller: _controller, //指明控制器加载更多使用
              ),
              onRefresh: _pullToRefresh,
            ),

onRefresh方法的实现_pullToRefresh,注意这里必须使用async 不然报错

 /**
   * 下拉刷新,必须异步async不然会报错
   */
  Future _pullToRefresh() async {
    currentPage = 0;
    movieList.clear();
    loadMoreData();
    return null;
  }

异步加载数据,注意:在Flutter中刷新数据使用的是setState,不然无效,数据不会刷新;数据的获取需要使用[]取值,不能使用对象“ . ”的取值方法!

//加载列表数据
loadMoreData() async {
    this.currentPage++;
    var start = (currentPage - 1) * pageSize;
    var url =
        "https://api.douban.com/v2/movie/$movieType?start=$start&count=$pageSize";
    Dio dio = new Dio();
    Response response = await dio.get(url);
    setState(() {
      movieList.addAll(response.data["subjects"]);
      totalSize = response.data["total"];
    });
  }

上拉加载更多

加载更多需要对ListView进行监听,所以需要进行监听器的设置,在State中进行监听器的初始化。

//初始化滚动监听器,加载更多使用
  ScrollController _controller = new ScrollController();

在构造器中设置监听

 //固定写法,初始化滚动监听器,加载更多使用
    _controller.addListener(() {
      var maxScroll = _controller.position.maxScrollExtent;
      var pixel = _controller.position.pixels;
      if (maxScroll == pixel && movieList.length < totalSize) {
        setState(() {
          loadMoreText = "正在加载中...";
          loadMoreTextStyle =
              new TextStyle(color: const Color(0xFF4483f6), fontSize: 14.0);
        });
        loadMoreData();
      } else {
        setState(() {
          loadMoreText = "没有更多数据";
          loadMoreTextStyle =
              new TextStyle(color: const Color(0xFF999999), fontSize: 14.0);
        });
      }
    });

在listView中添加监听controller方法

自此,Flutter如何实现下拉刷新和上拉加载更多完成…

整个列表页面代码参考如下:

import 'package:flutter/material.dart';
import 'package:dio/dio.dart';
import 'package:douban/pages/movie/movieDetail.dart';

class MovieList extends StatefulWidget {
  String movieType;
  //构造器传递数据(并且接收上个页面传递的数据)
  MovieList({Key key, this.movieType}) : super(key: key);
  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return new MovieListState(movieType: this.movieType);
  }
}

class MovieListState extends State<MovieList> {
  String movieType;
  String typeName;
  List movieList = new List();
  int currentPage = 0; //第一页
  int pageSize = 10; //页容量
  int totalSize = 0; //总条数
  String loadMoreText = "没有更多数据";
  TextStyle loadMoreTextStyle =
      new TextStyle(color: const Color(0xFF999999), fontSize: 14.0);
  TextStyle titleStyle =
      new TextStyle(color: const Color(0xFF757575), fontSize: 14.0);
  //初始化滚动监听器,加载更多使用
  ScrollController _controller = new ScrollController();

  /**
   * 构造器接收(MovieList)数据
   */
  MovieListState({Key key, this.movieType}) {
    //固定写法,初始化滚动监听器,加载更多使用
    _controller.addListener(() {
      var maxScroll = _controller.position.maxScrollExtent;
      var pixel = _controller.position.pixels;
      if (maxScroll == pixel && movieList.length < totalSize) {
        setState(() {
          loadMoreText = "正在加载中...";
          loadMoreTextStyle =
              new TextStyle(color: const Color(0xFF4483f6), fontSize: 14.0);
        });
        loadMoreData();
      } else {
        setState(() {
          loadMoreText = "没有更多数据";
          loadMoreTextStyle =
              new TextStyle(color: const Color(0xFF999999), fontSize: 14.0);
        });
      }
    });
  }

  //加载列表数据
  loadMoreData() async {
    this.currentPage++;
    var start = (currentPage - 1) * pageSize;
    var url =
        "https://api.douban.com/v2/movie/$movieType?start=$start&count=$pageSize";
    Dio dio = new Dio();
    Response response = await dio.get(url);
    setState(() {
      movieList.addAll(response.data["subjects"]);
      totalSize = response.data["total"];
    });
  }

  @override
  void initState() {
    super.initState();
    //设置当前导航栏的标题
    switch (movieType) {
      case "in_theaters":
        typeName = "正在热映";
        break;
      case "coming_soon":
        typeName = "即将上映";
        break;
      case "top250":
        typeName = "Top250";
        break;
    }

    //加载第一页数据
    loadMoreData();
  }

  /**
   * 下拉刷新,必须异步async不然会报错
   */
  Future _pullToRefresh() async {
    currentPage = 0;
    movieList.clear();
    loadMoreData();
    return null;
  }

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return new Scaffold(
      backgroundColor: Colors.white,
      appBar: new AppBar(
        leading: new IconButton(
          icon: const Icon(Icons.arrow_back),
          onPressed:null ,
        ),
        title: new Text(typeName != null ? typeName : "正在加载中...",
            style: new TextStyle(color: Colors.black)),
        backgroundColor: Colors.white,
      ),
      body: movieList.length == 0
          ? new Center(child: new CircularProgressIndicator())
          : new RefreshIndicator(
              color: const Color(0xFF4483f6),
              //下拉刷新
              child: ListView.builder(
                itemCount: movieList.length + 1,
                itemBuilder: (context, index) {
                  if (index == movieList.length) {
                    return _buildProgressMoreIndicator();
                  } else {
                    return renderRow(index, context);
                  }
                },
                controller: _controller, //指明控制器加载更多使用
              ),
              onRefresh: _pullToRefresh,
            ),
    );
  }

  /**
   * 加载更多进度条
   */
  Widget _buildProgressMoreIndicator() {
    return new Padding(
      padding: const EdgeInsets.all(15.0),
      child: new Center(
        child: new Text(loadMoreText, style: loadMoreTextStyle),
      ),
    );
  }

  /**
   * 列表的ltem
   */
  renderRow(index, context) {
    var movie = movieList[index];
    var id = movie["id"];
    var title = movie["title"];
    var type = movie["genres"].join("、");
    var year = movie["year"];
    var score = movie["rating"]["average"];
    return new Container(
        height: 200,
        color: Colors.white,
        child: new InkWell(
          onTap: () {
            Navigator.of(context).push(new MaterialPageRoute(
                builder: (ctx) => new MovieDetail(movieId: id)));
          },
          child: new Column(
            children: <Widget>[
              new Container(
                height: 199,
                // color: Colors.blue,
                child: new Row(
                  children: <Widget>[
                    new Container(
                      width: 120.0,
                      height: 180.0,
                      margin: const EdgeInsets.all(10.0),
                      child: Image.network(movie["images"]["small"]),
                    ),
                    Expanded(
                      child: new Container(
                        height: 180.0,
                        margin: const EdgeInsets.all(12.0),
                        child: new Column(
                          mainAxisAlignment: MainAxisAlignment.spaceBetween,
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: <Widget>[
                            new Text(
                              "电影名称:$title",
                              style: titleStyle,
                              overflow: TextOverflow.ellipsis,
                            ),
                            new Text(
                              "电影类型:$type",
                              style: titleStyle,
                              overflow: TextOverflow.ellipsis,
                            ),
                            new Text(
                              "上映年份:$year",
                              style: titleStyle,
                              overflow: TextOverflow.ellipsis,
                            ),
                            new Text(
                              "豆瓣评分:$score",
                              style: titleStyle,
                              overflow: TextOverflow.ellipsis,
                            )
                          ],
                        ),
                      ),
                    ),
                  ],
                ),
              ),
              //分割线
              new Divider(height: 1)
            ],
          ),
        ));
  }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Flutter listview如何实现下拉刷新上拉加载更多功能

    目录 下拉刷新 RefreshIndicator 上拉加载更多 总结: 下拉刷新 在Flutter中系统已经为我们提供了google material design的刷新功能 , 样式与原生Android一样. 我们可以使用RefreshIndicator组件来实现Flutter中的下拉刷新,下面们还是先来看下如何使用吧 RefreshIndicator 构造方法: const RefreshIndicator({ Key key, @required this.child, this.disp

  • Flutter 给列表增加下拉刷新和上滑加载更多功能

    有状态组件 当 Flutter 的页面需要动态更新数据的时候,就会涉及到 UI 组件需要根据数据变化更新,此时也就意味着组件有了"状态".这就类似 React 的类组件和函数组件(只是后续 React 使用了勾子函数实现了函数组件也可以有状态).在 Flutter 中,组件也分为无状态组件(StatelessWidget)和有状态组件(StatefulWidget),一般尽量使用无状态组件.但是如果组件本身需要维护自身状态的时候,就需要使用有状态组件了.有状态组件的定义形式如下: //

  • Flutter 实现下拉刷新上拉加载的示例代码

    本文介绍了Flutter 实现下拉刷新上拉加载的示例代码,分享给大家,具体如下: 效果图 使用方法 添加依赖 dependencies: pull_to_refresh: ^1.5.7 导入包 import 'package:pull_to_refresh/pull_to_refresh.dart'; 页面代码样例 class _MyHomePageState extends State<MyHomePage> { List<String> items = ["1&quo

  • Flutter ListView 上拉加载更多下拉刷新功能实现方法

    先上图 下拉刷新 跟原生开发一样,下拉刷新在flutter里提供的有组件实现 RefreshIndicator 一直不明白为啥组件中都提供下拉刷新,但就是没有上拉加载!! 我这请求接口数据用的是 http 库,是个第三方的是需要安装的 https://pub.dev/packages/http 用法如下 class MyHomePage extends StatefulWidget { MyHomePage({Key key}) : super(key: key); @override MyHo

  • Android仿XListView支持下拉刷新和上划加载更多的自定义RecyclerView

    首先给大家展示下效果图,感觉还不错,请继续往下阅读: 下拉刷新:        上划加载        在项目更新的过程中,遇到了一个将XListView换成recyclerView的需求,而且更换完之后大体效果不能变,但是对于下拉刷新这样的效果,谷歌给出的解决方案是把RecyclerView放在一个SwipeRefreshLayout中,但是这样其实是拉下一个小圆形控件实现的,和XListView的header效果不同.在网上找了很多的别人代码,都没有实现我想要的效果,于是自己动手写了一个.

  • vue移动端下拉刷新和上滑加载

    本文实例为大家分享了vue移动端下拉刷新和上滑加载的具体代码,供大家参考,具体内容如下 组件 <template> <div class="mu-load-more" @touchstart="touchStart($event)" @touchmove="touchMove($event)" @touchend="touchEnd($event)"> <div class="mu-re

  • 基于iScroll实现下拉刷新和上滑加载效果

    本文实例为大家分享了iScroll下拉刷新上滑加载展示的具体代码,供大家参考,具体内容如下 html代码: <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta name="viewport" content="width=devi

  • Flutter实现下拉刷新和上拉加载更多

    本文实例为大家分享了Flutter实现下拉刷新和上拉加载更多的具体代码,供大家参考,具体内容如下 效果 下拉刷新 如果实现下拉刷新,必须借助RefreshIndicator,在listview外面包裹一层RefreshIndicator,然后在RefreshIndicator里面实现onRefresh方法. body: movieList.length == 0           ? new Center(child: new CircularProgressIndicator())    

  • 使用MUI框架模拟手机端的下拉刷新和上拉加载功能

    mui框架基于htm5plus的XMLHttpRequest,封装了常用的Ajax函数,支持GET.POST请求方式,支持返回json.xml.html.text.script数据类型: 本着极简的设计原则,mui提供了mui.ajax方法,并在mui.ajax方法基础上,进一步简化出最常用的mui.get().mui.getJSON().mui.post()三个方法. 套用mui官方文档的一句话:"开发者只需关心业务逻辑,实现加载更多数据即可".真的是不错的框架. 想更多的了解这个框

  • dropload.js插件下拉刷新和上拉加载使用详解

    本文实例为大家分享了dropload.js下拉刷新和上拉加载的具体代码,供大家参考,具体内容如下 第一步,下载dropload插件,dropload插件下载地址 官方文档:https://github.com/ximan/dropload 第二步,将下载好的dropload插件中的dropload.css,dropload.min.js文件引入到页面中,注意还要引入 Jquery1.7 以上 或者 Zepto 二选一,不要同时都引用,因为dropload是基于jquery实现的 第三步,将以下代

  • android使用PullToRefresh实现下拉刷新和上拉加载

    PullToRefresh是一套实现非常好的下拉刷新库,它支持: 1.ListView 2.ExpandableListView 3.GridView 4.WebView 等多种常用的需要刷新的View类型,而且使用起来也十分方便. demo实例下载 下载完成,将它导入到eclipse中,作为一个library导入到你的工程中就好了. 一.废话少说,下拉刷新Go. 1.在你的布局文件中加上你想用的View就好了,比如这儿我想用一个支持下拉 刷新的ExpandableListView <com.h

  • H5基于iScroll实现下拉刷新和上拉加载更多

    前言 前一段有个手机端的项目需要用到下拉刷新和上拉加载更多的效果,脑海里第一反映就是微博那种效果,刚开始的理解有些偏差,以为下拉也是追加数据,上拉也是追加数据,后请教同事后发现其实下拉只是刷新最新数据而已,上拉是追加数据. 使用技巧 1.引用iScroll.js, 在初始化时添加两个事件监听:touchMove.DOMContentLoaded. 2.实现iScroll插件的onScrollEnd事件, 也就是在这个事件里调用你自己的ajax方法实现数据的刷新和追加. 3.上拉加载更多请求后台时

  • Android RecyclerView实现下拉刷新和上拉加载

    RecyclerView已经出来很久了,许许多多的项目都开始从ListView转战RecyclerView,那么,上拉加载和下拉刷新是一件很有必要的事情. 在ListView上,我们可以通过自己添加addHeadView和addFootView去添加头布局和底部局实现自定义的上拉和下拉,或者使用一些第三方库来简单的集成,例如Android-pulltorefresh或者android-Ultra-Pull-to-Refresh,后者的自定义更强,但需要自己实现上拉加载. 而在下面我们将用两种方式

随机推荐