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

1. 下拉刷新

Flutter中提供了组件 RefreshIndicator用于下拉刷新。

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

2. 上拉加载更多

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

其基本的实现方法是在该组件里添加控制器,在组件初始化时实例化ScrollController类型控制器,然后在初始化的initState( )中,给控制器添加addListener( )监听事件,在事件的回调函数中可以获得滚动的下拉距离整个页面的高度,然后判断这两个值的相差距离值,其值快接近时触发数据请求。

3. 代码实例

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


class NewsPage extends StatefulWidget {
    NewsPage({Key key}) : super(key: key);
    @override
    _NewsPageState createState() => _NewsPageState();
}

class _NewsPageState extends State<NewsPage> {
    // 当前页数
    int  _page = 1;
    // 页面数据
    List _list = [];
    // 是否还有
    bool _hasMore = true;
    // 滚动控制器
    ScrollController _scrollController = new ScrollController();
    @override
    void initState() {
        super.initState();
        this._getData();
        // 监听滚动事件
        _scrollController.addListener((){
            // 获取滚动条下拉的距离
            // print(_scrollController.position.pixels);
            // 获取整个页面的高度
            // print(_scrollController.position.maxScrollExtent);
            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._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
                )
            )
        );
    }
}

以下是下拉刷新的实现效果:

以下是上拉加载的实现效果:

猜你喜欢

转载自blog.csdn.net/weixin_40629244/article/details/112342422