列表高级交互 (Swipe/Refresh)
源:列表交互
本章介绍列表常见的两种交互:下拉刷新和侧滑删除。
1. 下拉刷新 (PullToRefresh)
API 变更
在 Material 3 1.3.0 之前,使用的是 PullToRefreshContainer + nestedScroll 的复杂写法。 从 Material 3 1.3.0 开始,Google 推荐使用更简单的 PullToRefreshBox。
kotlin
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun PullToRefreshSample() {
var isRefreshing by remember { mutableStateOf(false) }
val scope = rememberCoroutineScope()
PullToRefreshBox(
isRefreshing = isRefreshing,
onRefresh = {
scope.launch {
isRefreshing = true
delay(2000) // 模拟网络请求
isRefreshing = false
}
}
) {
LazyColumn(Modifier.fillMaxSize()) {
items(50) {
ListItem(headlineContent = { Text("Item $it") })
}
}
}
}2. 侧滑删除 (SwipeToDismiss)
M3 提供了 SwipeToDismissBox (旧版叫 SwipeToDismiss),支持从左或从右滑动。
kotlin
@Composable
fun SwipeToDismissList() {
val items = remember { mutableStateListOf("Item A", "Item B", "Item C") }
LazyColumn {
items(items, key = { it }) { item ->
SwipeToDismissItem(
item = item,
onRemove = { items.remove(item) }
)
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SwipeToDismissItem(item: String, onRemove: () -> Unit) {
val dismissState = rememberSwipeToDismissBoxState(
confirmValueChange = { value ->
if (value == SwipeToDismissBoxValue.EndToStart) {
onRemove()
true
} else {
false
}
}
)
SwipeToDismissBox(
state = dismissState,
backgroundContent = {
// 背景层:滑动时显示的内容 (如红色垃圾桶)
val color = if (dismissState.dismissDirection == SwipeToDismissBoxValue.EndToStart) {
Color.Red
} else Color.Transparent
Box(
Modifier
.fillMaxSize()
.background(color)
.padding(horizontal = 20.dp),
contentAlignment = Alignment.CenterEnd
) {
Icon(Icons.Default.Delete, contentDescription = "Delete", tint = Color.White)
}
},
content = {
// 前景层:实际列表项内容
ListItem(
headlineContent = { Text(item) },
modifier = Modifier.background(Color.White)
)
}
)
}