Flutter下拉刷新、上拉加载之flutter_easyrefresh

OK,史上最直接了当的flutter_easyrefresh接入,哈哈... 废话不多说,按照我的步骤来吧。

听说大家开始前还需要看一下效果图才有集成下去的动力?那么我满足大家。

视频效果展示:

图片展示:

​​​​​​​

集成开始:

一、在pubspec.yaml内导入插件。

1、插件版本和Flutter版本,如果对应不上,需根据 Flutter 的版本自行选择flutter_easyrefresh的版本。

2、Pub get一下

flutter_easyrefresh: ^2.2.2

二、定义EasyRefresh自带的头部和底部默认下拉刷新、上拉加载的样式。

1、在main.dart的 initState 对样式进行初始化。

EasyRefresh.defaultHeader = MaterialHeader(backgroundColor: Colors.white);
EasyRefresh.defaultFooter = BallPulseFooter(color: ColorConst.themeColor);

2、当然EasyRefresh还自带了很多炫酷的下拉刷新、上拉加载的样式,可自行根据下图查看。当然也可自定义下拉刷新、上拉加载的样式,可根据自带样式示例,自行定义。

三、下拉刷新、上拉加载示例

以下为完整的代码示例,完整复制需自行更改为您自己的接口数据。

1、本示例下拉刷新、上拉加载(header、footer)的样式引用的默认样式,不需要特殊设置这两个属性;

2、firstRefreshWidget这里设置为加载中弹窗,代码也相应给出。

3、emptyWidget为空数据情况显示的图片内容,代码也相应给出。

StatefulWidget:

import 'package:flutter/material.dart';
import 'package:flutter_easyrefresh/easy_refresh.dart';
import 'package:frame/bo/ListPageBo.dart';
import 'package:frame/common/color_const.dart';
import 'package:frame/common/size_const.dart';
import 'package:frame/dio/http_utils.dart';
import 'package:frame/utils/storage_util.dart';
import 'package:frame/widgets/custom_app_bar.dart';
import 'package:frame/widgets/empty_widget.dart';
import 'package:frame/widgets/first_refresh_widget.dart';

///列表分页
class ListPage extends StatefulWidget {
  const ListPage({super.key});

  @override
  _ListPageState createState() => _ListPageState();
}

class _ListPageState extends State<ListPage>
    with SingleTickerProviderStateMixin {
  final EasyRefreshController _controller = EasyRefreshController();
  int page = 1;
  bool isLastPage = true;
  List<Rows> listRow = [];

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

  ///网络请求
  void getData() {
    HttpUtils.doList(
        context,
        '1,3,6',
        '',
        StorageUtil.getInstance().getUnitStatus(),
        10,
        page, onSuccess: (value) {
      ///接口返回数据
      ListPageBo listBo = value;
      if (mounted) {
        setState(() {
          ///page==1时清除listRow数据,重新拉去数据,防止重复数据
          if (page == 1) {
            listRow.clear();
          }
          List<Rows>? rows = listBo.date?.rows;
          listRow.addAll(rows!);

          ///接口返回总页数(注:不是总条数)
          int? totalPage = listBo.date!.last;

          ///这里判断如果 接口返回的总页数 等于 当前上拉page++的页数 isLastPage=true,则表示已经是最后一页,就不可进行下拉加载操作。
          ///反之 接口返回的总页数 不等于 当前上拉page++的页数 isLastPage=false,表示还没到最后一页,可进行下拉加载操作。
          if (totalPage == page) {
            isLastPage = true;
          } else {
            isLastPage = false;
          }
        });
        _controller.finishRefresh();

        ///这里noMore=true 已到最后一页
        _controller.finishLoad(noMore: isLastPage);
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.grey[100],
      appBar: AppBarCustom(text: '列表分页', height: 50),
      body: Column(
        children: [
          Expanded(
              flex: 1,
              child: EasyRefresh(
                firstRefresh: true,
                enableControlFinishRefresh: true,
                enableControlFinishLoad: true,
                firstRefreshWidget: const FirstRefreshWidget(),
                emptyWidget: listRow.isEmpty
                    ? EmptyImgWidget(
                        title: '暂无数据,点击刷新',
                        onTap: () {
                          getData();
                        })
                    : null,
                controller: _controller,
                onRefresh: () async {
                  page = 1;
                  getData();
                },
                onLoad: () async {
                  page++;
                  getData();
                },
                child: buildBody(),
              )),
        ],
      ),
    );
  }

  Column buildBody() {
    return Column(
      children: [
        //文章列表
        ListView.separated(
          shrinkWrap: true,
          padding: const EdgeInsets.symmetric(
              horizontal: SizeConst.padding_horizontal),
          physics: const NeverScrollableScrollPhysics(),
          itemBuilder: (BuildContext context, int index) {
            return InkWell(
              onTap: () {
                // Get.toNamed(RouteString.DAY_COMPLETED_DETAIL_SY, arguments: {
                //   'argsData': widget.args,
                //   'listBo': listRow[index]
                // });
              },
              child: const Card(
                elevation: 3,
//                shadowColor:
//                    index == 1 ? ColorConst.blueColor : ColorConst.orangeColor,
                margin: EdgeInsets.only(left: 0, right: 0, top: 15, bottom: 0),
                color: Colors.green,
                shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.all(Radius.circular(5)),
                ),
                child: Column(
                  children: <Widget>[
                    SizedBox(height: 30),
                    Padding(
                      padding: EdgeInsets.all(10),
                      child: Text('Flutter 下拉刷新、上拉加载之flutter_easyrefresh'),
                    ),
                    SizedBox(height: 30)
                  ],
                ),
              ),
            );
          },
          itemCount: listRow.length,
          separatorBuilder: (BuildContext context, int index) {
            return const SizedBox(
              height: 0,
            );
          },
        ),
      ],
    );
  }
}

firstRefreshWidget:加载中弹窗。

这里SpinKitRotatingCircle为引用的flutter_spinkit插件内含很多炫酷的加载样式。

flutter_spinkit: ^5.2.0
import 'package:flutter/material.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:frame/common/color_const.dart';

class FirstRefreshWidget extends StatelessWidget {
  final String? progress;
  final String? text;

  const FirstRefreshWidget({super.key, this.progress, this.text});

  @override
  Widget build(BuildContext context) {
    return Center(
        child: SizedBox(
      height: 120.0,
      width: 120.0,
      child: Card(
        elevation: 0,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: <Widget>[
            Container(
              width: 50.0,
              height: 50.0,
              padding: const EdgeInsets.all(5),
              margin: const EdgeInsets.only(bottom: 5),
              child: const SpinKitRotatingCircle(
                  color: ColorConst.themeColor, size: 50.0),
            ),
            Container(
              alignment: Alignment.center,
              child: Text('${text ?? '正在加载...'}${progress ?? ''}'),
            ),
          ],
        ),
      ),
    ));
  }
}

emptyWidget:空数据情况

// ignore_for_file: file_names

import 'package:flutter/material.dart';
import 'package:frame/common/color_const.dart';
import 'package:frame/common/size_const.dart';

typedef OnTap = Function();

class EmptyImgWidget extends StatelessWidget {
  final String? title;
  final OnTap? onTap;

  const EmptyImgWidget({super.key, this.title, this.onTap});

  @override
  Widget build(BuildContext context) {
    return InkWell(
      child: Container(
        alignment: Alignment.center,
        padding: const EdgeInsets.symmetric(
            vertical: 12.0,
            horizontal: 12.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: <Widget>[
            Image.asset('assets/day/no_data_icon.png',
                width: 150.0, height: 150.0),
            Text(
              title ?? '暂无数据',
              style: const TextStyle(
                  fontSize: FontSizeConst.text_2s,
                  color: ColorConst.greyB2Color),
            ),
          ],
        ),
      ),
      onTap: () {
        if (onTap != null) {
          onTap!();
        }
      },
    );
  }
}

至此我们的flutter_easyrefresh集成已经介绍完了,如果有不完善的或者有疑问的地方欢迎大家的留言指出,我会尽快回复大家,谢谢。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值