首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何使用LazyColumn的animateItemPlacement()而不对更改进行自动转换?

如何使用LazyColumn的animateItemPlacement()而不对更改进行自动转换?
EN

Stack Overflow用户
提问于 2022-12-03 17:16:12
回答 1查看 25关注 0票数 2

我在一个类似样式的检查表中使用LazyColumn。列表首先显示所有待完成的项目,最后显示所有要完成的项目.敲击一个项目会切换它是否完成。

以下是我所做工作的MWE:

代码语言:javascript
运行
复制
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的解决方案,建议在第一个元素发生变化时回滚,但只有当列的第一个项是当前显示的第一个项目时,这才能解决问题。如果向下滚动第三个元素是最上面可见的元素并点击该元素,则该列仍将滚动以跟随该元素。

是否有任何方法将自动滚动与项目放置动画分离?两者似乎都依赖于LazyColumnkey参数?

EN

回答 1

Stack Overflow用户

发布于 2022-12-03 17:25:54

我没有尝试编译/运行您的代码,但是看起来您的代码有类似于this的问题,而且在LazyListState中也是如此。

代码语言:javascript
运行
复制
/**
 * 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)
}

我建议进行一项可能的工作,将第一项的动画设置为索引而不是备份数据的唯一标识符,从而牺牲第一项的动画。

代码语言:javascript
运行
复制
itemsIndexed(
        items = checkItems.sortedBy { it.checked.value },
        key = { index, item -> if (index == 0) index else item.id }
   ) { index, entry ->
        ...
   }

虽然我还没有回归任何用例与这种设置的懒散键,也无法解决您的问题,但您可以考虑尝试。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74668917

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档