CupertinoSliverRefreshControl
实现iOS风格下拉刷新内容控件的sliver小部件
CupertinoSliverRefreshControl是Flutter中iOS风格(Cupertino)的下拉刷新组件,用于在CustomScrollView或者NestedScrollView中实现类似iOS原生APP的下拉刷新效果。
核心特性
- iOS风格: 带有弹性动画和圆形进度指示器
- 基于Sliver: 必须配合
CustomScrollView使用 - 异步刷新: 通过
Future处理刷新逻辑
当作为滚动视图中的第一个Sliver插入,或置于其他仍允许在该Sliver前方产生滚动越界的Sliver(例如CupertinoSliverNavigationBar)之后时,此组件将:
- 通过传入的
builder允许用户在越界滚动区域中进行绘制 - 当越界滚动距离超过
refreshTriggerPullDistance时,触发提供的onRefresh函数 - 在
onRefresh返回的Future执行期间,继续保留refreshIndicatorExtent大小的空间,供builder持续绘制 - 一旦
onRefresh的Future完成,该组件将滚动消失
builder函数在调用时会收到当前的RefreshIndicatorMode状态,但在RefreshIndicatorMode.inactive状态下(此时没有可用空间,也无需构建内容)不会被调用。除此之外,当可用空间因越界滚动、onRefresh任务完成后Sliver滚动消失等情况发生变化时,builder函数将持续被调用。
ps: 在上一次刷新完成且指示器
Sliver至少回缩90%之前,无法触发新的刷新。
该组件仅可用于支持越界滚动的向下滚动垂直列表。换言之,在默认使用ClampingScrollPhysics(Android平台默认)的可滚动组件中无法触发刷新。若要在Android上启用越界滚动,可以使用支持越界滚动的物理效果,例如BouncingScrollPhysics。可以通过以下方式实现:
- 在构建可滚动组件时提供
BouncingScrollPhysics(可与AlwaysScrollableScrollPhysics结合使用) - 在可滚动组件上方插入一个使用
BouncingScrollPhysics的ScrollConfiguration - 使用
CupertinoApp,它会无视平台始终使用带有BouncingScrollPhysics的ScrollConfiguration
在典型应用中,该组件应插入在应用栏Sliver(如CupertinoSliverNavigationBar)和主滚动内容的Sliver之间。
代码示例
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
return const CupertinoApp(
title: 'CupertinoSliverRefreshControl Demo',
home: RefreshPage(),
);
}
}
class RefreshPage extends StatefulWidget {
const RefreshPage({super.key});
State<RefreshPage> createState() => _RefreshPageState();
}
class _RefreshPageState extends State<RefreshPage> {
List<String> items = List.generate(20, (index) => 'Item ${index + 1}');
// 模拟异步刷新
Future<void> _handleRefresh() async {
await Future.delayed(const Duration(seconds: 2)); // 模拟网络请求
setState(() {
items = List.generate(20, (index) => 'Refreshed Item ${index + 1}');
});
}
Widget build(BuildContext context) {
return CupertinoPageScaffold(
navigationBar: const CupertinoNavigationBar(
middle: Text('下拉刷新'),
),
child: CustomScrollView(
slivers: [
CupertinoSliverRefreshControl(
onRefresh: _handleRefresh,
// 可选:自定义刷新指示器颜色
// refreshIndicatorExtent: 100,
// builder: (context, refreshState, pulledExtent, ...) { ... },
),
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) => CupertinoListTile(
title: Text(items[index]),
),
childCount: items.length,
),
),
],
),
);
}
}
自定义刷新指示器
CupertinoSliverRefreshControl(
onRefresh: _handleRefresh,
builder: (
BuildContext context,
RefreshIndicatorMode refreshState,
double pulledExtent,
double refreshTriggerPullDistance,
double refreshIndicatorExtent,
) {
return Center(
child: CupertinoActivityIndicator(
animating: refreshState == RefreshIndicatorMode.refresh,
),
);
},
)
注意事项
- 必须配合
CustomScrollView: 不能直接在ListView中使用 - iOS风格限制: 在Android上可能看起来不协调,建议使用
RefreshIndicator(Material风格) - 异步逻辑: 确保
onRefresh返回的Future正确完成,否则会一直显示加载动画
进阶功能
- 结合
NestedScrollView: 实现嵌套滚动刷新(如TabBar+列表) - 动态控制刷新: 通过
GlobalKey或状态管理触发刷新
构造函数
CupertinoSliverRefreshControl.new({
Key? key,
double refreshTriggerPullDistance = _defaultRefreshTriggerPullDistance,
double refreshIndicatorExtent = _defaultRefreshIndicatorExtent,
RefreshControlIndicatorBuilder? builder = buildRefreshIndicator,
RefreshCallback? onRefresh
})
属性
| 参数名 | 类型 | 说明 |
|---|---|---|
onRefresh | Future<void> Function() | 必填,触发刷新时调用的异步函数。 |
refreshTriggerPullDistance | double | 触发刷新的下拉距离(默认 100.0)。 |
refreshIndicatorExtent | double | 刷新指示器的固定高度(默认 60.0)。 |
builder | Widget Function(...) | 自定义刷新指示器的 UI(可选)。 |