Flutter 简单封装http网络框架
Flutter 实现下拉刷新和自动加载更多
Flutter Banner封装
Flutter使用官方CustomScrollView实现复杂页面下拉刷新和加载更多
Flutter之Router和Navigator实现页面跳转
Flutter的基本应用
Flutter中ListView 是不具有下拉刷新和加载更多的功能的,当然Flutter 提供了RefreshIndicator实现了下拉刷新,但是这些组件仍然是需要在开发中再次封装便于维护。
@immutable
class SmartRefreshListView extends StatefulWidget {
final List<dynamic> data;
final Future<void> Function()? onRefresh;
final Future<void> Function()? onLoadMore;
final Widget Function(int index, dynamic item) itemBuilder;
/// 是否有下一页 ,由外部提供状态
final bool hasNextPage;
const SmartRefreshListView(
{super.key,
required this.data,
required this.itemBuilder,
this.hasNextPage = true,
this.onRefresh,
this.onLoadMore});
@override
State<SmartRefreshListView> createState() => _SmartRefreshListViewState();
}
class _SmartRefreshListViewState extends State<SmartRefreshListView> {
bool _isRefreshing = false;
bool _isLoading = false;
final ScrollController _scrollController = ScrollController();
@override
void initState() {
super.initState();
_scrollController.addListener(() {
if (_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent &&
widget.hasNextPage) {
_load();
}
});
}
@override
Widget build(BuildContext context) {
return RefreshIndicator(
onRefresh: _onRefresh,
child: ListView.builder(
controller: _scrollController,
itemCount: widget.data.length + 1,
itemBuilder: (context, index) {
if (index == widget.data.length) {
return _footer();
}
return widget.itemBuilder.call(index, widget.data[index]);
},
),
);
}
/// 下拉刷新 此方法结束,刷新完成
Future<void> _onRefresh() async {
if (_isLoading && _isRefreshing) {
return;
}
_isRefreshing = true;
await widget.onRefresh?.call();
_isRefreshing = false;
return;
}
/// 加载更多
Future<void> _load() async {
if (_isLoading && _isRefreshing) {
return;
}
_isLoading = true;
await widget.onLoadMore?.call();
_isLoading = false;
return;
}
_footer() {
if (!widget.hasNextPage) {
return Container(
padding: const EdgeInsets.only(top: 20, bottom: 20),
decoration: const BoxDecoration(color: Colors.white),
child: const Center(
child: Text("没有更多数据",
style: TextStyle(fontSize: 12, color: Colors.black)),
),
);
}
return const Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
height: 10,
width: 10,
child: CircularProgressIndicator(
strokeWidth: 2,
)),
SizedBox(width: 10),
Text("加载更多", style: TextStyle(fontSize: 16, color: Colors.black))
],
);
}
}
因为项目中的代码不能直接拿来使用,所以我重新简单的写了一遍,有很多功能没有暴露出来,代码很简单,组件内部维护刷新和加载状态,仅提供hasNextPage 是否有下一页供外部操作。
使用:
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "垂直列表",
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.white),
useMaterial3: false,
),
home: Scaffold(
appBar: AppBar(
title: const Text(
"垂直列表",
style: TextStyle(color: Colors.black),
),
backgroundColor: Colors.white),
body: SmartRefreshListView(
data: _list,
hasNextPage: hasNextPage,
onRefresh: () async {
print("onRefresh start");
await Future.delayed(const Duration(seconds: 3));
setState(() {
_list = List.generate(20, (idnex) {
return "onRefresh 第$idnex个";
});
hasNextPage = !hasNextPage;
});
print("onRefresh end");
},
onLoadMore: () async {
print("onLoadMore");
await Future.delayed(const Duration(seconds: 3));
setState(() {
var list = List.generate(10, (index) => "loading:$index");
_list.addAll(list);
hasNextPage = !hasNextPage;
});
print("onLoadMore end");
},
itemBuilder: (index, item) {
return ListTile(
leading: const Icon(Icons.people),
title: Text(item),
);
},
),
),
);
}
为了演示方便我使用 Future.delayed做了延时,真正项目中这里就是网络请求或者其他IO操作等。