【发布时间】:2022-12-04 02:08:57
【问题描述】:
我在类似清单的样式中使用LazyColumn。该列表首先显示所有待完成的项目,最后显示所有已完成的项目。点击一个项目会切换它是否完成。
这是我正在做的事情的 MWE:
data class TodoItem(val id: Int, val label: String, var isDone: Boolean)
@Composable
fun TodoCard(item: TodoItem, modifier: Modifier, onClick: () -> Unit) {
val imagePainterDone = rememberVectorPainter(Icons.Outlined.Done)
val imagePainterNotDone = rememberVectorPainter(Icons.Outlined.Add)
Card(
modifier
.padding(8.dp)
.fillMaxWidth()
.clickable {
onClick()
}) {
Row {
Image(
if (item.isDone) imagePainterDone else imagePainterNotDone,
null,
modifier = Modifier.size(80.dp)
)
Text(text = item.label)
}
}
}
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun ExampleColumn() {
val todoItems = remember {
val list = mutableStateListOf<TodoItem>()
for (i in 0..20) {
list.add(TodoItem(i, "Todo $i", isDone = false))
}
list
}
val sortedTodoItems by remember {
derivedStateOf { todoItems.sortedWith(compareBy({ it.isDone }, { it.id })) }
}
LazyColumn {
items(sortedTodoItems, key = {it.label}) { item ->
TodoCard(item = item, modifier = Modifier.animateItemPlacement()) {
val index = todoItems.indexOfFirst { it.label == item.label }
if (index < 0) return@TodoCard
todoItems[index] = todoItems[index].copy(isDone = !todoItems[index].isDone)
}
}
}
}
除了Modifier.animateItemPlacement() 引入的一个副作用外,这项工作很好:当切换第一个当前可见的列表元素时,LazyListState 将滚动以跟随该元素。
这不是我想要的(我更希望它保持在同一个索引处)。
我找到了this workaround,建议在第一个元素发生变化时滚动回第一个元素,但这仅在列的第一项是当前显示的第一个元素时才解决问题。如果向下滚动使得第三个元素出现在最顶部可见并点击该元素,该列仍将滚动以跟随它。
有没有办法将自动滚动与项目放置动画分离?两者似乎都依赖于 LazyColumn 的 key 参数?
【问题讨论】:
标签: android-jetpack-compose android-animation lazycolumn