【问题标题】:Update Jetpack Compose list with scroll position reset使用滚动位置重置更新 Jetpack Compose 列表
【发布时间】:2021-10-29 10:54:47
【问题描述】:

在我的应用程序中,我有 LazyColumn 显示的项目列表。我的列表可以更新字段,有时可以重新排序项目。每当我对项目进行重新排序时,我都需要在顶部显示第一个项目的列表。我想出了如下设置。列表仅在第一个重新排序事件时滚动到顶部。在使用reorder = true 连续更新列表时,我的列表没有滚动到顶部。 Compose 中通过从 ViewModel 发送状态来重置列表滚动位置(甚至强制重建撰写列表)的更好方法是什么?

class ViewItemsState(val items: List<ViewItem>, val scrollToTop: Boolean)

class ExampleViewModel() : ViewModel() {
    
    var itemsLiveData = MutableLiveData<ViewItemsState>()

}

@Composable
fun ExampleScreen(viewModel: ExampleViewModel = viewModel()) {

    val itemState  by viewModel.itemsLiveData.observeAsState()
    val coroutineScope = rememberCoroutineScope()
    val listState = rememberLazyListState()

    if (itemState.scrollToTop) {
        LaunchedEffect(coroutineScope) {
            Log.e("TAG", "TopCoinsScreen: scrollToTop" )
            listState.scrollToItem(0)
        }
    }

    LazyColumn(state = listState) {
        items(itemState.items) { item ->
            ItemCompose(
                item.name,
                item.value
            )
        }
    }
}

【问题讨论】:

  • 你不打算在列表绘制后滚动项目吗? view.post 之类的东西?
  • 我没有看到你重置scrollToTop,请提供minimal reproducible example。通常这种方法应该有效
  • @PhilipDukhov 重置是什么意思?我只是更新列表并设置参数scrollToTop = true or false
  • @Rafael 我说的是在滚动列表后将其设置为false。当您没有真正更新它并且只是连续多次设置为 true 时,可能会出现这种情况,在这种情况下它不应该滚动。

标签: android android-jetpack-compose


【解决方案1】:

仅当状态改变时才会触发重组。

有两件事要解决,

  1. 滚动完成后将scrollToTop 重置为false
  2. 在视图模型中将scrollToTop 存储为MutableStateLiveDataFlow 或任何其他反应元素。

目前scrollToTop 在数据类对象中存储为布尔值。重置该值不会触发可组合重组。

带有示例数据的示例代码,

class ViewItemsState(
    val items: List<String>,
)

class ExampleViewModel : ViewModel() {
    private var _itemsLiveData =
        MutableLiveData(
            ViewItemsState(
                items = Array(20) {
                    it.toString()
                }.toList(),
            )
        )
    val itemsLiveData: LiveData<ViewItemsState>
        get() = _itemsLiveData

    private var _scrollToTop = MutableLiveData(false)
    val scrollToTop: LiveData<Boolean>
        get() = _scrollToTop

    fun updateScrollToTop(scroll: Boolean) {
        _scrollToTop.postValue(scroll)
    }
}

@Composable
fun ExampleScreen(
    viewModel: ExampleViewModel = ExampleViewModel(),
) {
    val itemState by viewModel.itemsLiveData.observeAsState()
    val scrollToTop by viewModel.scrollToTop.observeAsState()
    val listState = rememberLazyListState()

    LaunchedEffect(
        key1 = scrollToTop,
    ) {
        if (scrollToTop == true) {
            listState.scrollToItem(0)
            viewModel.updateScrollToTop(false)
        }
    }

    Column {
        LazyColumn(
            state = listState,
            modifier = Modifier.weight(1f),
        ) {
            items(itemState?.items.orEmpty()) { item ->
                Text(
                    text = item,
                    modifier = Modifier.padding(16.dp),
                )
            }
        }
        Button(
            onClick = {
                viewModel.updateScrollToTop(true)
            },
        ) {
            Text(text = "Scroll")
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-20
    • 2019-09-07
    • 2022-08-20
    • 2021-05-26
    • 2020-09-25
    • 1970-01-01
    相关资源
    最近更新 更多