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集成已经介绍完了,如果有不完善的或者有疑问的地方欢迎大家的留言指出,我会尽快回复大家,谢谢。