借助“下拉刷新”组件,用户可以在应用内容开头向下拖动以刷新数据。
API Surface
使用 PullToRefreshBox
可组合项实现“拉动刷新”功能,该功能可用作可滚动内容的容器。以下关键参数可控制刷新行为和外观:
isRefreshing
:一个布尔值,指示刷新操作目前是否正在进行。onRefresh
:在用户发起刷新时执行的 lambda 函数。indicator
:自定义在“拉动以刷新”时绘制的指示器。
基本示例
以下代码段演示了 PullToRefreshBox
的基本用法:
@Composable fun PullToRefreshBasicSample( items: List<String>, isRefreshing: Boolean, onRefresh: () -> Unit, modifier: Modifier = Modifier ) { PullToRefreshBox( isRefreshing = isRefreshing, onRefresh = onRefresh, modifier = modifier ) { LazyColumn(Modifier.fillMaxSize()) { items(items) { ListItem({ Text(text = it) }) } } } }
代码要点
PullToRefreshBox
会封装LazyColumn
,后者用于显示字符串列表。PullToRefreshBox
需要isRefreshing
和onRefresh
参数。PullToRefreshBox
块中的内容代表可滚动内容。
结果
此视频演示了上述代码中的基本下拉刷新实现:
高级示例:自定义指示器颜色
@Composable fun PullToRefreshCustomStyleSample( items: List<String>, isRefreshing: Boolean, onRefresh: () -> Unit, modifier: Modifier = Modifier ) { val state = rememberPullToRefreshState() PullToRefreshBox( isRefreshing = isRefreshing, onRefresh = onRefresh, modifier = modifier, state = state, indicator = { Indicator( modifier = Modifier.align(Alignment.TopCenter), isRefreshing = isRefreshing, containerColor = MaterialTheme.colorScheme.primaryContainer, color = MaterialTheme.colorScheme.onPrimaryContainer, state = state ) }, ) { LazyColumn(Modifier.fillMaxSize()) { items(items) { ListItem({ Text(text = it) }) } } } }
代码要点
- 指示器颜色是通过
indicator
参数中的containerColor
和color
属性来自定义的。 rememberPullToRefreshState()
用于管理刷新操作的状态。您可以将此状态与indicator
参数搭配使用。
结果
此视频展示了带有彩色指示器的下拉刷新实现:
高级示例:创建完全自定义的指示器
您可以利用现有的可组合项和动画创建复杂的自定义指示器。以下代码段演示了如何在下拉刷新实现中创建完全自定义的指示器:
@Composable fun PullToRefreshCustomIndicatorSample( items: List<String>, isRefreshing: Boolean, onRefresh: () -> Unit, modifier: Modifier = Modifier ) { val state = rememberPullToRefreshState() PullToRefreshBox( isRefreshing = isRefreshing, onRefresh = onRefresh, modifier = modifier, state = state, indicator = { MyCustomIndicator( state = state, isRefreshing = isRefreshing, modifier = Modifier.align(Alignment.TopCenter) ) } ) { LazyColumn(Modifier.fillMaxSize()) { items(items) { ListItem({ Text(text = it) }) } } } } // ... @Composable fun MyCustomIndicator( state: PullToRefreshState, isRefreshing: Boolean, modifier: Modifier = Modifier, ) { Box( modifier = modifier.pullToRefreshIndicator( state = state, isRefreshing = isRefreshing, containerColor = PullToRefreshDefaults.containerColor, threshold = PositionalThreshold ), contentAlignment = Alignment.Center ) { Crossfade( targetState = isRefreshing, animationSpec = tween(durationMillis = CROSSFADE_DURATION_MILLIS), modifier = Modifier.align(Alignment.Center) ) { refreshing -> if (refreshing) { CircularProgressIndicator(Modifier.size(SPINNER_SIZE)) } else { val distanceFraction = { state.distanceFraction.coerceIn(0f, 1f) } Icon( imageVector = Icons.Filled.CloudDownload, contentDescription = "Refresh", modifier = Modifier .size(18.dp) .graphicsLayer { val progress = distanceFraction() this.alpha = progress this.scaleX = progress this.scaleY = progress } ) } } } }
代码要点
- 上一个代码段使用了该库提供的
Indicator
。此代码段会创建一个名为MyCustomIndicator
的自定义指示器可组合项。在此可组合项中,pullToRefreshIndicator
修饰符会处理定位和触发刷新。 - 与前面的代码段一样,
PullToRefreshState
实例已被提取,因此可以将同一实例同时传递给PullToRefreshBox
和pullToRefreshModifier
。 - 容器颜色和位置阈值来自
PullToRefreshDefaults
类。这样,您就可以重复使用 Material 库中的默认行为和样式,同时仅自定义您感兴趣的元素。 MyCustomIndicator
使用Crossfade
在云图标和CircularProgressIndicator
之间进行转换。云朵图标会随着用户拉动而放大,并在刷新操作开始时转换为CircularProgressIndicator
。targetState
使用isRefreshing
来确定要显示哪种状态(云图标或圆形进度指示器)。animationSpec
为过渡定义了tween
动画,其指定时长为CROSSFADE_DURATION_MILLIS
。state.distanceFraction
表示用户向下拉动了多远,范围从0f
(未拉动)到1f
(完全拉动)。graphicsLayer
修饰符可修改缩放比例和透明度。
结果
此视频展示了上方代码中的自定义指示器: