gpt4 book ai didi

android - Jetpack 撰写 : how to reset LazyListState?

转载 作者:行者123 更新时间:2023-12-05 02:25:57 27 4
gpt4 key购买 nike

我有一个带有嵌套 LazyRowsLazyColumn(类似于 Netflix 或 Spotify 主页提要)。简而言之,我遇到的问题是当页面内容更改时,嵌套 LazyRow 的滚动位置不会重置。

例如,用户向下滚动主页,滚动第 3 个水平部分以查看第 5 个项目,刷新主页,加载新页面内容。但是第3个水平部分仍然显示第5个而不是重置到初始位置。

就代码而言,这里有一些 fragment :

在 HomeScreen 可组合项中:

    Scaffold {
when (val viewState = viewModel.stateFlow.collectAsState().value) {
is ViewState.Success -> {
Box {
with(viewState.data) {
LazyColumn {
itemsIndexed(sections) { index, section ->
LazyRow{}
//etc.
}
}
}
}

}

在 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)
}
}
}

现在我已经设法添加额外的代码,以便在用户刷新主屏幕时将主页的 LazyColumn 滚动到屏幕顶部。但是,我仍然不知道对嵌套的 LazyRows 执行此操作的最佳方法是什么。我不想保留对他们的 LazyListState 的引用,因为该解决方案不能很好地扩展。但是,我对为什么在发出新状态并显示新 LazyRows 时不重置滚动位置感到困惑。这是 Compose 中的错误吗?还是我遗漏了什么?

最佳答案

How to reset a LazyListState

恐怕没有 API 可以将可组合项“重置”回其创世纪 状态(如果这就是您所说的“重置”的意思),在这种情况下您需要这些 惰性 组件在向其中一个元素添加元素时滚动到特定位置,然后您必须执行惰性状态滚动操作。

For example, user scrolls down the home page, scrolls the 3rdhorizontal sections to see the 5th item, refreshes the home page, thenew page content is loaded. But the 3rd horizontal section still showsthe 5th instead of resetting to the initial position.

我在这里假设您总是在 LazyRow 的第一个索引中插入新项目,并且您想滚动到开头(0 索引)每次添加新元素时。

I do not want to keep a reference to their LazyListState as that solution does not scale well

But I was hoping there's an easier solution as this one does not scale well.

我不知道你所说的“扩展性不好”是什么意思,但是正如@vitidev 所提到的,你可以利用 LaunchedEffect,你也不需要持有每个的引用LazyList 状态实例,如果你想在添加新元素时滚动到 0 索引。

所以我假设您的 ViewModel 或任何与流程或协程相关的问题都没有。

根据我的理解,您可以简单地调整您的设计以避免创建和持有过多的 LazyListState 引用。考虑下面的示例,虽然它的代码相当长,但它们都是可复制和粘贴的,因此您可以毫无问题地编译它们。

data class NestedItem(
val display: String
)

val row1 = mutableStateListOf(
NestedItem("Row 1 Item 1"),
NestedItem("Row 1 Item 2"),
NestedItem("Row 1 Item 3"),
NestedItem("Row 1 Item 4"),
NestedItem("Row 1 Item 5"),
)

val row2 = mutableStateListOf(
NestedItem("Row 2 Item 1"),
NestedItem("Row 2 Item 2"),
NestedItem("Row 2 Item 3"),
NestedItem("Row 2 Item 4"),
NestedItem("Row 2 Item 5"),
)

val row3 = mutableStateListOf(
NestedItem("Row 3 Item 1"),
NestedItem("Row 3 Item 2"),
NestedItem("Row 3 Item 3"),
NestedItem("Row 3 Item 4"),
NestedItem("Row 3 Item 5"),
)

val row4 = mutableStateListOf(
NestedItem("Row 4 Item 1"),
NestedItem("Row 4 Item 2"),
NestedItem("Row 4 Item 3"),
NestedItem("Row 4 Item 4"),
NestedItem("Row 4 Item 5"),
)

var nest = listOf(
row1, row2, row3, row4
)

@Composable
fun MyScreen(nestedList: List<List<NestedItem>>) {
Column {
Row(
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight(),
horizontalArrangement = Arrangement.SpaceEvenly
) {
repeat(4) { idx ->
Button(onClick = {
when (idx) {
0 -> {
row1.add(0, NestedItem("New Item At Row ${idx + 1}"))
}
1 -> {
row2.add(0, NestedItem("New Item At Row ${idx + 1}"))
}
2 -> {
row3.add(0, NestedItem("New Item At Row ${idx + 1}"))
}
3 -> {
row4.add(0, NestedItem("New Item At Row ${idx + 1}"))
}
}
}) {
Text(text = "R${idx + 1} Add")
}
}
}

MyScreen(nestedList = nest)
}
}


@Composable
fun MyContent(nestedList: List<List<NestedItem>>) {
LazyColumn(
modifier = Modifier.fillMaxWidth()
) {
items(nestedList) {
MyEveryRow(rowItems = it)
}
}
}

// we leave all the scrolling to LaunchedEffect here everytime the size changes
@Composable
fun MyEveryRow(rowItems: List<NestedItem> ) {

val lazyRowState = rememberLazyListState()

LaunchedEffect(rowItems.size) {
lazyRowState.animateScrollToItem(0)
}

LazyRow(
state = lazyRowState
) {
items(rowItems) { item ->
MyCell(item = item)
}
}
}

@Composable
fun MyCell(item: NestedItem) {

Box(
modifier = Modifier
.size(width = 150.dp, height = 150.dp)
.border(BorderStroke(Dp.Hairline, Color.DarkGray)),
contentAlignment = Alignment.Center
) {
Text(text = item.display)
}
}

上面的代码将产生这个输出,将新项目添加到第一个索引并滚动到它,而不需要有太多的 LazyListState 引用。

enter image description here

这里我们使用项目的大小作为此 LaunchedEffect 的键,因此当添加新元素时,将执行此副作用。

LaunchedEffect(rowItems.size) { 
lazyRowState.animateScrollToItem(0)
}

关于android - Jetpack 撰写 : how to reset LazyListState?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74164414/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com