Jorge MartÃn
03/28/2025, 4:26 PMHorizontalPager
, we have this weird issue:
val pagerState = rememberPagerState(state.currentIndex, 0f) {
state.listData.size
}
HorizontalPager(
state = pagerState,
// Pre-load previous and next pages
beyondViewportPageCount = 1,
key = { index -> state.listData[index].pagerKey },
) { page ->
// Pager item needs to know when it's the 'selected/visible' item
PagerItem(isDisplayed = page == pagerState.settledPage)
}
With this code, we were seeing an issue when reloading the list that acts as a data source, and having it change from something like [A, B, C]
(A
being the visible item), to something like [D, A, B, C]
would:
1. First, re-create the pages inside the HorizontalPager
lambda, so we'd have pagerState.pageCount
== 4 now.
2. Then, the pagerState.settledPage
/`pagerState.currentPage` changes from 0
to 1
since the HorizontalPager
is capable of keeping the same item focused.
However, this means for 1 recomposition we have the index of A
change from 0
to 1
while the settledPage
is still 0
, so isDisplayed
will be false, then on the next recomposition, the pager state's currentPage and settledPage values will change from 0
to 1
too, and isDisplayed
will have the right value again. This is particularly important for us because isDisplayed
dictates whether some media in the pager item should play or pause, so we have some brief stuttering.
So what I've ended up doing is doing val isDisplayed by remember(pagerState.settledPage) { page == pagerState.settledPage }
so the value is only recomputed when either we need a new item (not re-composing an existing one) or the pager state actually changes into the update value and the value will be computed properly. So while this seems to work, I'm wondering: is this behaviour normal, is there some better way to avoid this desynchronization between the pager item provider and the current page value in the pager state?