重新组合后保持 LazyColumn 滚动位置
Maintain LazyColumn scroll position after re-composition
我正在构建一个可组合的屏幕,比如 PostScreen
,其中 GridView
中显示多个 post,当用户点击其中任何一个时,我将导航至 DetailScreen
其中 post 显示在带有多个关联按钮(如评论)的较大框中。
我的逻辑是,当用户单击 PostScreen
中的任何 post 时,使用 PostScreen
中的索引滚动到 DetailScreen
中的该索引。问题是,当用户点击任何 post(并到达 DetailScreen
),然后向上(或向下)移动然后点击操作(例如,像 post),协同程序操作已启动,但索引正在重置并且 DetailScreen
滚动到原始索引而不是停留在喜欢的 post。我将如何解决这个问题? (我知道 rememberLazyListState()
)
@Composable
fun DetailScreen(
viewModel: MyViewModel,
index: Int? // index is coming from navGraph
) {
val postIndex by remember { mutableStateOf(index) }
val scope = rememberCoroutineScope()
val posts = remember(viewModel) { viewModel.posts }.collectAsLazyPagingItems()
Scaffold(
topBar = { MyTopBar() }
) { innerPadding ->
JustNestedScreen(
modifier = Modifier.padding(innerPadding),
posts = posts,
onLike = { post ->
// This is causing index to reset, maybe due to re-composition
scope.launch {
viewModel.toggleLike(
postId = post.postId,
isLiked = post.isLiked
)
}
},
indexToScroll = postIndex
)
}
}
@Composable
fun JustNestedScreen(
modifier: Modifier = Modifier,
posts: LazyPagingItems<ExplorePost>,
onLike: (Post) -> Unit,
indexToScroll: Int? = null
) {
val scope = rememberCoroutineScope()
val listState = rememberLazyListState()
LazyColumn(
modifier = modifier
.fillMaxSize()
.background(MaterialTheme.colors.background),
state = listState
) {
items(posts) { post ->
post?.let {
// Display image in box and some buttons
FeedPostItem(
post = it,
onLike = onLike,
)
}
}
indexToScroll?.let { index ->
scope.launch {
listState.scrollToItem(index = index)
}
}
}
}
使用LaunchedEffect。 LaunchedEffect
的块只是 运行 第一次,然后每次更改密钥时。如果你只想 运行 它一次,使用 Unit
或 listState
作为键:
LaunchedEffect(listState) {
indexToScroll?.let { index ->
listState.scrollToItem(index = index)
}
}
我正在构建一个可组合的屏幕,比如 PostScreen
,其中 GridView
中显示多个 post,当用户点击其中任何一个时,我将导航至 DetailScreen
其中 post 显示在带有多个关联按钮(如评论)的较大框中。
我的逻辑是,当用户单击 PostScreen
中的任何 post 时,使用 PostScreen
中的索引滚动到 DetailScreen
中的该索引。问题是,当用户点击任何 post(并到达 DetailScreen
),然后向上(或向下)移动然后点击操作(例如,像 post),协同程序操作已启动,但索引正在重置并且 DetailScreen
滚动到原始索引而不是停留在喜欢的 post。我将如何解决这个问题? (我知道 rememberLazyListState()
)
@Composable
fun DetailScreen(
viewModel: MyViewModel,
index: Int? // index is coming from navGraph
) {
val postIndex by remember { mutableStateOf(index) }
val scope = rememberCoroutineScope()
val posts = remember(viewModel) { viewModel.posts }.collectAsLazyPagingItems()
Scaffold(
topBar = { MyTopBar() }
) { innerPadding ->
JustNestedScreen(
modifier = Modifier.padding(innerPadding),
posts = posts,
onLike = { post ->
// This is causing index to reset, maybe due to re-composition
scope.launch {
viewModel.toggleLike(
postId = post.postId,
isLiked = post.isLiked
)
}
},
indexToScroll = postIndex
)
}
}
@Composable
fun JustNestedScreen(
modifier: Modifier = Modifier,
posts: LazyPagingItems<ExplorePost>,
onLike: (Post) -> Unit,
indexToScroll: Int? = null
) {
val scope = rememberCoroutineScope()
val listState = rememberLazyListState()
LazyColumn(
modifier = modifier
.fillMaxSize()
.background(MaterialTheme.colors.background),
state = listState
) {
items(posts) { post ->
post?.let {
// Display image in box and some buttons
FeedPostItem(
post = it,
onLike = onLike,
)
}
}
indexToScroll?.let { index ->
scope.launch {
listState.scrollToItem(index = index)
}
}
}
}
使用LaunchedEffect。 LaunchedEffect
的块只是 运行 第一次,然后每次更改密钥时。如果你只想 运行 它一次,使用 Unit
或 listState
作为键:
LaunchedEffect(listState) {
indexToScroll?.let { index ->
listState.scrollToItem(index = index)
}
}