簡體   English   中英

使用滾動位置重置更新 Jetpack Compose 列表

[英]Update Jetpack Compose list with scroll position reset

在我的應用程序中,我使用 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
            )
        }
    }
}

僅當狀態發生變化時才會觸發重組。

有兩件事要解決這個問題,

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM