M3E 设计系统
M3E 设计系统 · androidx.compose.material3
Pull to Refresh:接入 Expressive LoadingIndicator1.5.0-alpha25
连接刷新状态、加载指示器和协程任务,避免只换指示器却忘记完整刷新数据流。
最后更新 2026-07-31
Expressive 改变的是 indicator
catalog 的 PullToRefreshWithLoadingIndicatorSample 使用新的 contained LoadingIndicator。刷新流程本身仍然是:用户下拉 → isRefreshing = true → 执行任务 → 更新内容 → false。
PullToRefreshBox(
isRefreshing = isRefreshing,
onRefresh = { viewModel.refresh() },
indicator = {
PullToRefreshDefaults.LoadingIndicator(
state = state,
isRefreshing = isRefreshing,
)
},
) { Content() }不要在 composable 中直接阻塞
官方 samples 通过 coroutine 执行刷新并在结束时复位状态。真实项目更适合让 ViewModel 暴露 refreshing 状态,避免旋转屏幕或重组时重复启动请求。
实验边界
PullToRefreshDefaults 中与 LoadingIndicator 对应的颜色和 composable 标记了 Expressive 实验 API;基础 PullToRefresh API 有自己的 Material3 experimental 边界,按编译器提示在最小范围 opt-in。
复制即用
带 Expressive LoadingIndicator 的下拉刷新:
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
import androidx.compose.material3.PullToRefreshBox
import androidx.compose.material3.PullToRefreshDefaults
import androidx.compose.material3.rememberPullToRefreshState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
@Composable
fun RefreshableList(content: @Composable () -> Unit) {
var isRefreshing by remember { mutableStateOf(false) }
val state = rememberPullToRefreshState()
PullToRefreshBox(
isRefreshing = isRefreshing,
onRefresh = {
// 用协程执行刷新,结束后复位
},
indicator = {
PullToRefreshDefaults.LoadingIndicator(
state = state,
isRefreshing = isRefreshing,
)
},
) {
content()
}
}真实项目建议把刷新状态放进 ViewModel,避免重组或旋转屏幕时重复请求。