【问题标题】:Android Compose LazyList - keep scrolling position when new items are added to the top of the listAndroid Compose LazyList - 当新项目添加到列表顶部时保持滚动位置
【发布时间】:2022-03-18 12:08:29
【问题描述】:

这是我添加任何新项目之前的原始列表

当我在列表末尾添加一个新项目时,不滚动,第一个项目仍保留在该位置

但是当我将新项目添加到列表的开头时,所有旧项目都会下移。请注意,New item 0 不再位于列表的最顶端

我怎样才能做到,如果我在列表的开头添加一个新项目,旧项目仍然保留在确切的位置。这些新项目只有在用户向上滚动时才可见,而不是向下推所有内容。如果我没记错的话,这是RecyclerView的默认行为

这是我的代码: MainActivity.kt

class MainActivity : ComponentActivity() {
    private val list = MutableStateFlow<List<String>>(emptyList())

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            EmptyComposeTheme {
                val items = list.collectAsState()
                Box(Modifier.fillMaxSize()) {
                    LazyColumn(
                        Modifier.fillMaxSize(),
                    ) {
                        itemsIndexed(items.value) { index: Int, item: String ->
                            Text(item, color = MaterialTheme.colors.onSurface)
                        }
                    }
                    FloatingActionButton(onClick = {
                        val oldList = list.value.toMutableList()
                        oldList.add("New item ${oldList.size}")
                        list.value = oldList
                    }, Modifier.align(Alignment.BottomStart)) {
                       Text("Click me!")
                    }
                    FloatingActionButton(onClick = {
                        val oldList = list.value.toMutableList()
                        oldList.add(0, "New item reversed ${oldList.size}")
                        list.value = oldList
                    }, Modifier.align(Alignment.BottomEnd)) {
                        Text("Click other me!")
                    }
                }
            }
        }
    }
}

我正在使用 Compose 版本1.0.1

【问题讨论】:

    标签: android android-jetpack-compose


    【解决方案1】:

    LazyComunitemsIndexedand index 在关键参数中解决了我的问题。

    LazyColumn(
        state = listState
    ) {
        itemsIndexed(list, key = {index, item->
           index + item.hashcode() // Including index in the key param solved my problem
        }) {
           ....
        }
    }
    

    【讨论】:

    • 您能否提供一个参考来解释它的工作原理?
    • 根据文档:当您指定键时,滚动位置将基于键保持,这意味着如果您在当前可见项目之前添加/删除项目,则具有给定键的项目将是保留为第一个可见的。
    【解决方案2】:

    基本上你的目标是控制滚动位置,如更详细的描述here

    在以您的代码为基础时,您可以执行以下操作:

    val items = list.collectAsState()
    val listState = rememberLazyListState()
    val coroutineScope = rememberCoroutineScope()
    
    Box(Modifier.fillMaxSize()) {
        LazyColumn(
            state = listState,
            modifier = Modifier.fillMaxSize(),
        ) {
            ...
        }
        
        ...
        
        FloatingActionButton(onClick = {
            val currentIndex = listState.firstVisibleItemIndex + 1
            val oldList = list.value.toMutableList()
            oldList.add(0, "New item reversed ${oldList.size}")
            list.value = oldList
    
            coroutineScope.launch {
                listState.scrollToItem(currentIndex)
            }
        }, Modifier.align(Alignment.BottomEnd)) {
            Text("Click other me!")
        }
    }
    

    【讨论】:

      【解决方案3】:

      你可以像这样将关键参数添加到 LazyColumn,但是如果你的 firstVisibleIndex = 0,那么问题没有解决,我不知道为什么它:

      LazyColumn(
          state = listState,
          modifier = Modifier.fillMaxSize(),
          key = { item -> item.id} // or any unique value
      ) {
          ...
      }
      

      【讨论】:

      • 正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center
      猜你喜欢
      • 2019-01-21
      • 1970-01-01
      • 2020-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-19
      相关资源
      最近更新 更多