I was wondering if there is a way or a resource I could refer to in order to achieve a side effect on a LazyRow when an item is scrolled?
The side effect is basically to call a function in the viewModel to alter the state of the list's state.
- The side effect should be only executed only if the current firstVisibleItemIndex after
- scroll is different than before
The side effect should not be executed the item is not fully scrolled
I am implementing a fullscreen
LazyRowitems with a snap behavior
So far I have tried NestedScrollConnection
class OnMoodItemScrolled : NestedScrollConnection {
override suspend fun onPostFling(consumed: Velocity, available: Velocity): Velocity {
viewModel.fetchItems()
return super.onPostFling(consumed, available)
}
}
The issue with the above is that the side effect is going to be executed anyway even-though the item displayed after the scroll is the same as before the scroll.
I also tried to collecting the listState interaction as the following
val firstVisibleItem: Int = remember { sectionItemListState.firstVisibleItemIndex }
sectionItemListState.interactionSource.collectIsDraggedAsState().let {
if (firstVisibleItem != sectionItemListState.firstVisibleItemIndex) {
viewModel.fetchItems()
}
}
The issue with the above is that the side effect is going to be executed the second the composable is composed for the first time.
I solved my issue using a
LaunchedEffectwith 2 keys.Using both
currentVisibleItemIndexandcurrentVisibleItemScrollOffsetas keys will make sure that theLaunchedEffectwill be triggered whenever one of them changes. Moreover, checking if thepreviousVisibleItemIndexis different than thecurrentVisibleItemIndexwill ensure that we only trigger this effect only if the visible item is changing. However, this condition will true also if the use has partially scrolled and since I have a snapping effect it will go back to the previous position. Which will result in triggering the effect twice. In order to make sure that we only trigger the effect only in case were we actually scrolled to the next/previous fully visible position we need to rely on thescrollOffset.