我在一个类似样式的检查表中使用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()
引入的一个副作用:当切换第一个当前可见的list元素时,LazyListState
将滚动到元素后面。
这不是我想要的(我更希望它保持在相同的指数上)。
我找到了this的解决方案,建议在第一个元素发生变化时回滚,但只有当列的第一个项是当前显示的第一个项目时,这才能解决问题。如果向下滚动第三个元素是最上面可见的元素并点击该元素,则该列仍将滚动以跟随该元素。
是否有任何方法将自动滚动与项目放置动画分离?两者似乎都依赖于LazyColumn
的key
参数?
发布于 2022-12-03 17:25:54
我没有尝试编译/运行您的代码,但是看起来您的代码有类似于this的问题,而且在LazyListState
中也是如此。
/**
* When the user provided custom keys for the items we can try to detect when there were
* items added or removed before our current first visible item and keep this item
* as the first visible one even given that its index has been changed.
*/
internal fun updateScrollPositionIfTheFirstItemWasMoved(itemsProvider: LazyListItemsProvider) {
scrollPosition.updateScrollPositionIfTheFirstItemWasMoved(itemsProvider)
}
我建议进行一项可能的工作,将第一项的动画设置为索引而不是备份数据的唯一标识符,从而牺牲第一项的动画。
itemsIndexed(
items = checkItems.sortedBy { it.checked.value },
key = { index, item -> if (index == 0) index else item.id }
) { index, entry ->
...
}
虽然我还没有回归任何用例与这种设置的懒散键,也无法解决您的问题,但您可以考虑尝试。
https://stackoverflow.com/questions/74668917
复制相似问题