Flutter 中下拉刷新需要用到 RefreshIndicator 组件,一般在 ScrollView 或 ListView 外包一层 RefreshIndicator 组件即可。
1. 常见用法
Future _onRefresh() async {
//......实现刷新逻辑
}
@override
Widget build(BuildContext context) {
return RefreshIndicator(
onRefresh: _onRefresh,
child: SingleChildScrollView(
child: Container(),
));
}
使用很简单,只需要实现 onRefresh 函数即可,这也是一个 Future 函数,当该 Future 执行完毕时,刷新操作也就完成了。是不是很奇怪,当我们用原生代码写下拉刷新时,通常需要定义一个状态来表示刷新状态,到 Flutter 这里居然啥都不用管。当触发下拉刷新时,就会执行 onRefresh 函数,只要该函数没有执行完毕,UI 上就一直显示的是刷新状态,一旦该函数执行完毕,UI 状态也会自动改变成刷新完成。
2. 怎么触发自动刷新
通常我们进入某个页面时,希望一进去就会触发自动下拉刷新,但是找了一圈发现没有什么属性可设置。经过一番研究,发现 RefreshIndicator 也是一个有状态组件,我们可直接获取该组件的状态,通过它的状态来手动触发下拉刷新。这就需要用到每个 Widget 都会有的 Key
属性了,通过 key 可以得到其对应的状态。具体代码如下:
//自定义 RefreshIndicatorState 类型的 Key
final GlobalKey<RefreshIndicatorState> _refreshKey = GlobalKey();
@override
void initState() {
super.initState();
//必须在组件挂载运行的第一帧后执行,否则 _refreshKey 还没有与组件状态关联起来
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
//关键代码,直接触发下拉刷新
_refreshKey.currentState?.show();
});
}
Future _onRefresh() async {
//......实现刷新逻辑
}
@override
Widget build(BuildContext context) {
return RefreshIndicator(
key: _refreshKey, //自定义 key,需要通过 key 获取到对应的 State
onRefresh: _onRefresh,
child: SingleChildScrollView(
child: Container(),
));
}
3. 页面不能滚动时无法触发下拉刷新
如果页面内容很少,在一屏内不能滚动,你会发现无法触发下拉刷新。解决这个问题,需要设置 ScrollView 的 physics 属性。
最终完整解决方案如下:
//自定义 RefreshIndicatorState 类型的 Key
final GlobalKey<RefreshIndicatorState> _refreshKey = GlobalKey();
@override
void initState() {
super.initState();
//必须在组件挂载运行的第一帧后执行,否则 _refreshKey 还没有与组件状态关联起来
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
//关键代码,直接触发下拉刷新
_refreshKey.currentState?.show();
});
}
Future _onRefresh() async {
//......实现刷新逻辑
}
@override
Widget build(BuildContext context) {
return RefreshIndicator(
key: _refreshKey, //自定义 key,需要通过 key 获取到对应的 State
onRefresh: _onRefresh,
child: SingleChildScrollView(
physics: const AlwaysScrollableScrollPhysics(),
child: Container(),
));
}
默认情况下,当 ScrollView 包裹的内容太少时,是不会触发滚动事件的,这样也就不会触发下拉刷新。AlwaysScrollableScrollPhysics
则可以在这种情况下,触发滚动事件。