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

2022-08-24 10:42:07

本文实例为大家分享了Flutter实现下拉刷新和上拉加载更多的具体代码,供大家参考,具体内容如下效果下拉刷新如果实现下拉刷新,必须借助RefreshIndicator,在listview外面包裹一层R...

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

效果

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

下拉刷新

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

body: movieList.length == 0
     ? new Center(child: new CircularProgrpythonessIndicator())
     : 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实现下拉刷新和上拉加载更多

自此,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 =
    "ht编程tps://api.douban.com/v2/movie/$movieType?start=$start&count=$pageSize";
  Dio dio = new Dio();
  Response response = await dio.get(url);
  setState(() {
   movieList.addAll(respandroidonse.data[js"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)
      ],
     ),
    ));
 }
}

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