flutter实战——实现下拉刷新和加载更多功能

问题背景

移动端日常开发过程中,下拉刷新和加载更多是很常见的功能点,现在一起看下flutter是如何实现下拉刷新和加载更多的。

问题分析

1、通过Dio框架获取网络请求

var url = "http://www.phonegap100.com/appapi.php?a=getPortalList&catid=20&page=$_page";
        Response result = await Dio().get(url);
        var list = json.decode(result.data)["result"];

2、Flutter中提供了组件 RefreshIndicator用于下拉刷新 其基本的实现方法是在该组件添加onRefresh事件,当用户下拉刷新时会触发该事件,在该事件中可以用调用一个延时任务Future.delayed( ),在延时任务的回调中重新请求数据即可。

RefreshIndicator(
                  child: ListView.builder(
                    ......
                  ),
                  // 2、回调下拉刷新事件
                  onRefresh:this._onRefresh
              )

3、flutter中主要通过使用 ListView.builder( ) 添加控制器来实现上拉加载更多

ListView.builder(
                    // 上拉加载控制器
                    controller: _scrollController,
                    itemCount: this._list.length,
                    itemBuilder: (context,index){

                      Widget tip = Text("");
                      // 当渲染到最后一条数据时,加载动画提示
                      if(index == this._list.length-1){
                        tip = _getMoreWidget();
                      }
                      return Column(
                        children: <Widget>[
                          ListTile(
                              title:Text(
                                "${this._list[index]["title"]}",
                                maxLines:1,
                              )
                          ),
                          Divider(),
                          // 加载提示
                          tip
                        ],
                      );
                    },
                  ),

问题解决

上面分析了flutter实现下拉刷新和加载更多的关键环节,完整代码如下:

import 'dart:convert';

import 'package:dio/dio.dart';
import 'package:flutter/material.dart';

class Test extends StatefulWidget {
  _TestState createState() => _TestState();
}

class _TestState extends State<Test> {
    // 页数
    int _page = 1;
    // 页面数据列表
    List _list = [];
    // 标志位:是否有更多数据
    bool _hasMore = true;
    // 滚动控制器
    ScrollController _scrollController = new ScrollController();

    @override
    void initState() {
      super.initState();
      this._getData();
      // 监听滚动事件
      _scrollController.addListener((){
        if(_scrollController.position.pixels>_scrollController.position.maxScrollExtent-40){
          this._getData();
        }
      });
    }

    // 获取数据列表
    void _getData() async{
      if(this._hasMore){
        var url = "http://www.phonegap100.com/appapi.php?a=getPortalList&catid=20&page=$_page";
        Response result = await Dio().get(url);
        var list = json.decode(result.data)["result"];

        setState(() {
          // 拼接数据
          this._list.addAll(list);
          // 页数累加
          this._page++;
        });

        if(list.length<20){
          setState(() {
            // 关闭加载
            this._hasMore = false;
          });
        }
      }
    }

    // 下拉刷新
    Future<void> _onRefresh() async{
      print("下拉刷新");
      // 持续两秒
      await Future.delayed(Duration(milliseconds:2000),(){
        // 清空数据进行刷新
        this._list.clear();
        this._page = 1;
        this._getData();
      });
    }

    // 加载动画
    Widget _getMoreWidget() {
      // 如果还有数据
      if(this._hasMore){
        return Center(
          child: Padding(
            padding: EdgeInsets.all(10.0),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: <Widget>[
                Text(
                  '加载中',
                  style: TextStyle(fontSize: 16.0),
                ),
                // 加载图标
                CircularProgressIndicator(
                  strokeWidth: 1.0,
                )
              ],
            ),
          ),
        );
      }else{
        return Center(
          child: Text("...我是有底线的..."),
        );
      }
    }

    @override
    Widget build(BuildContext context) {
      return Container(
          child:Scaffold(
              appBar: AppBar(
                  title:Text("新闻列表")
              ),
              body:this._list.length==0?this._getMoreWidget():RefreshIndicator(
                  child: ListView.builder(
                    // 上拉加载控制器
                    controller: _scrollController,
                    itemCount: this._list.length,
                    itemBuilder: (context,index){

                      Widget tip = Text("");
                      // 当渲染到最后一条数据时,加载动画提示
                      if(index == this._list.length-1){
                        tip = _getMoreWidget();
                      }
                      return Column(
                        children: <Widget>[
                          ListTile(
                              title:Text(
                                "${this._list[index]["title"]}",
                                maxLines:1,
                              )
                          ),
                          Divider(),
                          // 加载提示
                          tip
                        ],
                      );
                    },
                  ),
                  // 下拉刷新事件
                  onRefresh:this._onRefresh
              )
          )
      );
    }
}

运行结果如下: 1681112606931.gif

问题总结

本文主要是介绍了flutter是如何实现下拉刷新和加载更多的,有兴趣的同学可以进一步深入研究。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值