flutter 下拉刷新 上拉加载

 

完整的代码, 可以复制引用

_UpDown是一个State类,其中主要有两个功能:下拉刷新和上拉加载更多。

_getData函数用于从服务器获取数据。当数据长度小于预期的pageSize时(如20),它会将pageFlag设置为false,这表示没有更多的数据可以加载。

下拉刷新功能通过RefreshIndicator实现,当用户下拉列表时,它会触发onRefresh方法。

上拉加载更多功能是通过添加滚动监听器来实现的。当滚动到列表底部时,会调用_getData方法加载更多数据。

getMoreTips是一个StatelessWidget,用于显示加载提示(正在加载或没有更多数据)。

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

    /// UpDown 类是 StatefulWidget 类,用于展示内容并处理状态
    class UpDown extends StatefulWidget {
        UpDown({Key key});

    // 创建状态管理类的实例
        _UpDown createState() => _UpDown();
    }

    class _UpDown extends State<UpDown> {

        // 当前页数,默认从第一页开始
        int page = 1;

        // 定义每页应该加载的内容数量
        final int pageSize = 20;

        // 一个标志,用于判断是否还有更多内容可以加载
        bool pageFlag = true;

        // 存储从 API 加载的内容
        List list = [];

        // 控制页面滚动的控制器
        final ScrollController _scrollController = ScrollController();

        @override
        void initState() {
            super.initState();

            // 初始化时加载数据
            _getData();

            // 添加滚动监听,用于检测是否滚动到底部,以便加载更多内容
            _scrollController.addListener(_loadMore);
        }

        @override
        void dispose() {
            // 销毁控制器,释放资源
            _scrollController.dispose();
            super.dispose();
        }

        // 上拉加载更多的功能
        _loadMore() {
            if (_scrollController.position.pixels >= _scrollController.position.maxScrollExtent) {
                _getData();
            }
        }

        // 从 API 获取数据的方法
        _getData() async {
        // 如果没有更多内容可以加载,直接返回
        if (!pageFlag) return;

        // 发起 GET 请求从 API 获取内容
        final response = await Dio().get(
            'http://www.phonegap100.com/appapi.php?a=getPortalList&catid=20&page=$page');
        final res = json.decode(response.data)['result'];

        // 更新状态:添加新加载的内容到列表,并增加页数
        setState(() {
        list.addAll(res);
        page++;
        if (res.length < pageSize) {
        pageFlag = false;
    }
    });
    }

    @override
    Widget build(BuildContext context) {
        // 如果已经加载了内容,则展示内容;否则展示加载状态
        return list.isNotEmpty
            ? RefreshIndicator(
                onRefresh: _handleRefresh,
            child: ListView.builder(
            controller: _scrollController,
            itemCount: list.length,
            itemBuilder: (context, index) => Column(
            children: <Widget>[
            Text('12312'),
            if (index == list.length - 1) GetMoreTips(flag: pageFlag),
            ],
            ),
            ),
            )
            : GetMoreTips(flag: pageFlag);
            }

            // 下拉刷新的处理方法
            Future<void> _handleRefresh() async {
                await Future.delayed(Duration(milliseconds: 2000));
                setState(() {
                list.clear();
                page = 1;
                _getData();
            });
            }
                }

                /// 显示加载状态的小部件
                class GetMoreTips extends StatelessWidget {
                    final bool flag;

                    GetMoreTips({Key key, @required this.flag}) : super(key: key);

                    @override
                    Widget build(BuildContext context) {
                    // 根据 flag 的值来展示相应的加载状态
                    return Center(
                    child: flag
                    ? Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: <Widget>[
                    Container(
                    padding: EdgeInsets.only(top: Screen.width(20), bottom: Screen.width(20)),
                    child: Text('正在加载...', style: TextStyle(fontSize: Screen.width(28), color: Colors.grey)),
                    ),
                    Container(
                    margin: EdgeInsets.only(left: Screen.width(20)),
                    width: Screen.width(45),
                    height: Screen.width(45),
                    child: CircularProgressIndicator(strokeWidth: 2, valueColor: AlwaysStoppedAnimation<Color>(ColorGather.colorMain())),
                    ),
                    ],
                    )
                    : Container(
                    padding: EdgeInsets.only(top: Screen.width(20), bottom: Screen.width(20)),
                    child: Text('没有更多数据...', style: TextStyle(fontSize: Screen.width(28), color: Colors.grey)),
                    ),
                    );
                }
                }

posted on   完美前端  阅读(638)  评论(0编辑  收藏  举报

编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

点击右上角即可分享
微信分享提示