菲利普的解决方案对您有用。但是,我发布此内容是为了确保您了解以下原因:
A. 滚动不平稳。
B. 当您快速滚动列表时,它会滚动到底部。
A. 的解释:
这是因为您正在使用
animateScollTo
。如果调用次数过多,我曾经遇到过该方法出现问题。
这个问题的解释在于
Lazy
scrollers如何在内部处理其子项。您知道,
Lazy
scrollers只显示大数据集的一个小窗口以供用户查看。为了实现这一点,它使用内部缓存。所以,屏幕上的项目和当前窗口顶部和底部的几个项目都被缓存。
现在,由于在您的代码中,在Composable的主体(即
items
范围)内进行了一次
animateScrollTo(size)
调用,因此代码将在每次组合时执行。
因此,在每次重新组合时,
animateScrollTo
方法和用户触摸输入之间存在活动冲突。当用户以不太快的方式滚动时,会发生以下情况-用户按下,轻轻滚动,然后松开手指。现在,请记住,只要手指按下,他们就会感觉到
animateScrollTo
没有效果(因为用户正在主动保持滚动条的位置,因此系统不会将其滚过)。因此,在用户滚动时,列表前面的一些项目被缓存,但是
animateScrollTo
不起作用。然后,由于运动足够缓慢,因此惯性造成的滚动距离不是问题,因为列表已经有足够的缓存项可以显示距离。这也解释了第二个问题。
B. 的解释:
当您快速滚动列表时,与上述情况(慢滚动)完全相同。只是这一次,惯性使列表向前滚动得太快,以至于无法基于内部缓存处理滚动条,因此存在活动重新组合。但是,现在由于没有活动的用户输入(他们已经将手指从屏幕上拿开),因此它实际上会
animate
到底部,因为在这里
animateScrollTo
方法没有冲突。
只要按下手指,无论您滚动得多快,它都不会滚到底部(请测试!)
现在来解决实际问题。Philip的答案非常棒。唯一的问题是,如果开发人员也有一个删除项目的实现,这个方法可能行不通。因为只监测了列表的大小,所以当添加或删除项时,它将滚动到末尾。为了解决这个问题,我们实际上需要某种参考值。因此,您可以自己实现某些内容来提供一个布尔变量,用于确认是否已添加了一个项目,或者您可以使用以下内容。
@Composable
fun ResultsList(results: List<Pair<Square, Boolean>>) {
val currentSize by rememberSaveable { mutableStateOf (results.size) }
var isItemAdded by mutableStateO(results.size > currentSize)
LaunchedEffect (isItemAdded){
if(isItemAdded){
listState.animateScrollToItem(results.size)
currentSize = results.size
}
}
val listState = rememberLazyListState()
LazyRow(state = listState) {
items(results) { result ->
ResultsItem(result.first, result.second)
}
}
}
这样可以确保正常的行为。当然,如果有其他需要帮助的地方,请告诉我。
gif
。或者,您所说的“不流畅”是什么意思? - Richard Onslow Roper