I'm building a composable screen, say PostScreen
where multiple posts are shown in GridView
and when user click on any of them, I'll navigate to DetailScreen
where posts are shown in larger box with multiple buttons associated (like, comment).
My logic is, when user click on any post in PostScreen
, use an index from PostScreen
to scroll to that index in DetailScreen
. Issue is, when user click on any post (and arrive to DetailScreen
), then move up (or down) wards and then click on action (for example, like a post), a coroutine operation is launched but index is getting reset and DetailScreen
scroll to original index instead of staying at liked post. How would i resolve this? (I know about 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)
}
}
}
}
Use LaunchedEffect. LaunchedEffect
's block is only run the first time and then every time keys are changed. If you only want to run it once, use Unit
or listState
as a key:
LaunchedEffect(listState) {
indexToScroll?.let { index ->
listState.scrollToItem(index = index)
}
}