Im investigating an issue where in extremely rare ...
# compose
z
Im investigating an issue where in extremely rare cases, my
HorizontalPager
will get stuck in between two pages when I programmatically scroll between them. (code & details in 🧵_)_
I suspect that the problem is that Im trying to synchronize the pager with my external state. Very simplified, but you can imagine that I have some class with
mutableStateOf<Int>
that decides which page the pager should start at, or scroll to. This gets updated both programatically, and in reaction to user scroll events. In the scenario where the pager got stuck, these are the events that lead up to it: • Pages are [A, B, C] • User is at page B (at index 1) • The backing list to the pager is reordered -> [B, A, C] • User is at page B (now at index 0) • The pager is set to programatically scroll to A And the pager is now stuck between B & A. (this is extremely rare, but very confusing when it does happen).
My code to react & tell page changes looks like this: (and my HorizontalPager uses keys for its items)
Copy code
@Composable
fun rememberPagerState(
    page: Int,
    pageCount: () -> Int,
    onPageSelected: (Int) -> Unit,
): PagerState {
    val state =
        rememberPagerState(
            initialPage = page,
            pageCount = pageCount,
        )

    val currentPage by rememberUpdatedState(page)
    val currentOnPageSelected by rememberUpdatedState(onPageSelected)

    LaunchedEffect(state) {
        snapshotFlow(state::targetPage).distinctUntilChanged().collect { newPage ->
            if (newPage != currentPage) {
                delay(50.milliseconds)

                if (newPage == state.targetPage) {
                    currentOnPageSelected(newPage)
                }
            }
        }
    }

    LaunchedEffect(currentPage) {
        if (state.settledPage != currentPage && !state.isScrollInProgress) {
            state.animateScrollToPage(currentPage)
        }
    }

    return state
}
I suspect that if I change
PagerState.targetPage
to instead use
PagerState.currentPage
(updated when the pager has settled on the page, instead of mid-scroll) this bug will be fixed. But, I need the fast updates so that I can update elements outside of the pager to match the page the user is at faster (currentPage takes roughly 0.5s longer and its very noticeable).
z
I’ve found PagerState very hard to synchronize other stuff with. I wish you the best 😅
🙂 1
🙏🏽 1
t
Yes good luck with that plenty of edge cases.
homer disappear 1