Jetpack Compose,设置新数据时如何重置 LazyColumn 位置?

Posted

技术标签:

【中文标题】Jetpack Compose,设置新数据时如何重置 LazyColumn 位置?【英文标题】:Jetpack Compose, how to reset LazyColumn position when new data are set? 【发布时间】:2022-01-20 11:26:04 【问题描述】:

我正在使用 LazyColumn 在 Compose 中创建搜索页面,一切正常,除了 LazyColumn 在数据更改时返回到第一项的想要行为。

这是我对惰性列的实际实现:

@Composable
fun <DataType : Any> GenericListView(
    itemsList: SnapshotStateList<DataType>, // this list comes from the search page viewmodel
    modifier: Modifier = Modifier.fillMaxSize(),
    spacing: Dp = 24.dp,
    padding: PaddingValues = PaddingValues(0.dp),
    item: @Composable (DataType) -> Unit
) 

    val listState: LazyListState = rememberLazyListState()
    val coroutineScope = rememberCoroutineScope()

    LazyColumn(
        verticalArrangement = Arrangement.spacedBy(spacing),
        state = listState,
        modifier = modifier.padding(padding)
    ) 
        items(itemsList) 
            item(it)
        
    

    SideEffect 
        Log.i("->->->->->->->", "side effect launched")
        coroutineScope.launch 
            listState.scrollToItem(0)
        
    

正如文档所说,每次重构函数时都应该调用SideEffect, 但它似乎只能在带有SideEffect 断点的调试模式下工作,否则,它仅在第一次创建整个页面时才有效。

我已经尝试使用LaunchedEffect 而不是SideEffect,将itemsList 用作key,但没有任何反应。

为什么我的代码只能在调试模式下工作? 或者更好的是,在设置新数据时重置位置的现有解决方案?

【问题讨论】:

【参考方案1】:

SideEffect 不起作用,因为当 SnapshotStateList 更改时 Compose 实际上并没有重新组合整个视图:它看到只有 LazyColumn 正在使用这个状态值,所以只有这个函数需要重新组合。

要使其正常工作,您可以将 itemsList 更改为 List&lt;DataType&gt; 并传递普通列表,例如 itemsList = mutableStateList.toList() - 它会强制整个视图重新组合。


LaunchedEffect 与传递的SnapshotStateList 出于同样的原因不起作用:它比较状态容器的地址,而该地址没有改变。要比较项目本身,您可以再次将其转换为普通列表:在这种情况下,它将通过项目哈希进行比较。

LaunchedEffect(itemsList.toList()) 

【讨论】:

以上是关于Jetpack Compose,设置新数据时如何重置 LazyColumn 位置?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Jetpack Compose 中为 LazyColumn 设置默认滚动位置而没有任何反馈或动画

Jetpack Compose ScrollableTabRow 如何调整最小宽度

在 Jetpack Compose 中单击时如何禁用涟漪效应

Jetpack Compose:如何以编程方式将主题从浅色模式更改为深色模式 onClick

尝试运行 jetpack compose 仪器测试时如何克服此构建错误

Jetpack Compose ScrollableTabRow 如何调整最小宽度