Zia*_*abi 7 android kotlin android-jetpack-compose lazycolumn compose-recomposition
我有一个LazyColumn嵌套的LazyRows(类似于 Netflix 或 Spotify 主页提要)。简而言之,我遇到的问题是,当页面内容更改时,嵌套 LazyRows 的滚动位置不会重置。
例如,用户向下滚动主页,滚动第三个水平部分看到第五项,刷新主页,加载新的页面内容。但第三个水平部分仍然显示第五个而不是重置到初始位置。
在代码方面,这里有一些片段:
在主屏幕可组合项中:
Scaffold {
when (val viewState = viewModel.stateFlow.collectAsState().value) {
is ViewState.Success -> {
Box {
with(viewState.data) {
LazyColumn {
itemsIndexed(sections) { index, section ->
LazyRow{}
//etc.
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
在 HomeViewModel 中,当用户刷新主屏幕时,调用此函数:
private val _stateFlow = MutableStateFlow<ViewState<HomePage>>(ViewState.Loading)
val stateFlow: StateFlow<ViewState<HomePage>>
get() = _stateFlow
fun loadHomeScreen() {
viewModelScope.launch {
repository.getHomePage()
.collect {
_stateFlow.tryEmit(it)
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在,我已成功添加额外的代码,以便在用户刷新主屏幕时将主页的 LazyColumn 滚动到屏幕顶部。但是,我仍然不知道对于嵌套 LazyRows 来说最好的方法是什么。我不想保留对他们的引用,LazyListState因为该解决方案无法很好地扩展。但是,我很困惑为什么在发出新状态并显示新的 LazyRows 时滚动位置没有被重置。这是 Compose 中的错误吗?或者我错过了什么?
\n\n如何重置
\nLazyListState
恐怕没有 API 可以将可组合项“重置”回其创世状态(如果这就是您所说的“重置”的意思),在这种情况下,您希望这些Lazy组件滚动到特定的位置当一个元素添加到其中之一时,您必须执行惰性状态滚动操作。
\n\n例如,用户向下滚动主页,滚动第三个水平部分以查看第五项,刷新主页,加载新页面内容。但第三个水平部分仍然显示\n第五个而不是重置到初始位置。
\n
我在这里假设您总是在 a 的第一个索引中插入新项目,并且每次添加新元素时LazyRow您都希望滚动到开头(索引)。0
\n\n我不想保留对其 LazyListState 的引用,因为该解决方案无法很好地扩展
\n\xe2\x80\xa6
\n但我希望有一个更简单的解决方案,因为这个解决方案的扩展性不好。
\n
我不知道你所说的“扩展性不好”是什么意思,但正如@vitidev提到的,你可以利用,如果你想滚动到,LaunchedEffect你也不需要保存每个状态实例的引用添加新元素时的索引。LazyList0
ViewModel所以我假设您的或与流程或协程相关的任何内容都没有问题。
根据我的理解,您可以简单地调整您的设计,以避免创建和保留太多LazyListState参考。考虑下面的示例,虽然它的代码相当长,但它们都是可复制和粘贴的,因此您可以毫无问题地编译它们。
data class NestedItem(\n val display: String\n)\n\nval row1 = mutableStateListOf(\n NestedItem("Row 1 Item 1"),\n NestedItem("Row 1 Item 2"),\n NestedItem("Row 1 Item 3"),\n NestedItem("Row 1 Item 4"),\n NestedItem("Row 1 Item 5"),\n)\n\nval row2 = mutableStateListOf(\n NestedItem("Row 2 Item 1"),\n NestedItem("Row 2 Item 2"),\n NestedItem("Row 2 Item 3"),\n NestedItem("Row 2 Item 4"),\n NestedItem("Row 2 Item 5"),\n)\n\nval row3 = mutableStateListOf(\n NestedItem("Row 3 Item 1"),\n NestedItem("Row 3 Item 2"),\n NestedItem("Row 3 Item 3"),\n NestedItem("Row 3 Item 4"),\n NestedItem("Row 3 Item 5"),\n)\n\nval row4 = mutableStateListOf(\n NestedItem("Row 4 Item 1"),\n NestedItem("Row 4 Item 2"),\n NestedItem("Row 4 Item 3"),\n NestedItem("Row 4 Item 4"),\n NestedItem("Row 4 Item 5"),\n)\n\nvar nest = listOf(\n row1, row2, row3, row4\n)\n\n@Composable\nfun MyScreen(nestedList: List<List<NestedItem>>) {\n Column {\n Row(\n modifier = Modifier\n .fillMaxWidth()\n .wrapContentHeight(),\n horizontalArrangement = Arrangement.SpaceEvenly\n ) {\n repeat(4) { idx ->\n Button(onClick = {\n when (idx) {\n 0 -> {\n row1.add(0, NestedItem("New Item At Row ${idx + 1}"))\n }\n 1 -> {\n row2.add(0, NestedItem("New Item At Row ${idx + 1}"))\n }\n 2 -> {\n row3.add(0, NestedItem("New Item At Row ${idx + 1}"))\n }\n 3 -> {\n row4.add(0, NestedItem("New Item At Row ${idx + 1}"))\n }\n }\n }) {\n Text(text = "R${idx + 1} Add")\n }\n }\n }\n\n MyScreen(nestedList = nest)\n }\n}\n\n\n@Composable\nfun MyContent(nestedList: List<List<NestedItem>>) {\n LazyColumn(\n modifier = Modifier.fillMaxWidth()\n ) {\n items(nestedList) {\n MyEveryRow(rowItems = it)\n }\n }\n}\n\n// we leave all the scrolling to LaunchedEffect here everytime the size changes\n@Composable\nfun MyEveryRow(rowItems: List<NestedItem> ) {\n\n val lazyRowState = rememberLazyListState()\n \n LaunchedEffect(rowItems.size) { \n lazyRowState.animateScrollToItem(0)\n }\n\n LazyRow(\n state = lazyRowState\n ) {\n items(rowItems) { item ->\n MyCell(item = item)\n }\n }\n}\n\n@Composable\nfun MyCell(item: NestedItem) {\n\n Box(\n modifier = Modifier\n .size(width = 150.dp, height = 150.dp)\n .border(BorderStroke(Dp.Hairline, Color.DarkGray)),\n contentAlignment = Alignment.Center\n ) {\n Text(text = item.display)\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n上面的代码将产生此输出,将新项目添加到第一个索引并滚动到它,而不需要太多LazyListState引用。
在这里,我们使用项目的大小作为关键,LaunchedEffect因此当添加新元素时,将执行此副作用。
LaunchedEffect(rowItems.size) { \n lazyRowState.animateScrollToItem(0)\n}\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
2547 次 |
| 最近记录: |