[英]Update Jetpack Compose list with scroll position reset
In my app I have list of items shown with LazyColumn.在我的应用程序中,我使用 LazyColumn 显示了项目列表。 My list can update fields and sometime reorder items.
我的列表可以更新字段,有时还可以重新排序项目。 Whenever I have reorder of items I need to show list with first item at the top.
每当我对项目重新排序时,我都需要在顶部显示第一个项目的列表。 I came up with setup like the one below.
我想出了如下设置。 List scrolls to the top only on the first reorder event.
列表仅在第一个重新排序事件时滚动到顶部。 On consecutive list update with
reorder = true
, my list not scrolling to the top.在使用
reorder = true
连续更新列表时,我的列表不会滚动到顶部。 What is the better approach in Compose to reset list scroll position (or even force rebuilding compose list) by sending state from ViewModel? 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
)
}
}
}
Recomposition is triggered only when a state changes.仅当状态发生变化时才会触发重组。
Two things to fix in this,有两件事要解决这个问题,
scrollToTop
to false
once scrolling completes.scrollToTop
重置为false
。scrollToTop
in the view model as a MutableState
, LiveData
, Flow
, or any other reactive element.scrollToTop
作为MutableState
、 LiveData
、 Flow
或任何其他反应式元素存储在视图模型中。 Currently scrollToTop
is stored as a boolean in a data class object.目前
scrollToTop
在数据类对象中存储为布尔值。 Resetting the value will not trigger a Composable recomposition.重置该值不会触发可组合重组。
Example code with sample data,带有示例数据的示例代码,
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.