What I am trying to achieve is if there are two horizontal pagers, then on swiping top one to left then the bottom horizontal pager should swipe to right and vice-versa, have tried using pagerState scrollBy method but not getting desired output
First of all, you need to determine which pager is scrolled and which one should follow it. This can be done with isScrollInProgress
, I use it inside derivedStateOf
to avoid unnecessary re-compositions.
Then I run LaunchedEffect
. I'm passing pair of pager states in needed order, or null, as a key
, so LaunchedEffect
will be re-launched when scrolling stops/starts. Using snapshotFlow
, it is possible to track changes in the result of a block whose calculations depend on state changes.
PagerState
has scroll position information in the properties currentPage
and currentPageOffset
. scrollToPage
takes only 0..1
values for page offset, but currentPageOffset
can be less than zero when scrolling backward.
Suppose currentPage = 2
and currentPageOffset = -0.1
. In this case, I will get 1.9
in pagePart
, and I need to split it back to get 1
and 0.9
. To do this I use divideAndRemainder
: it will return a list of the form listOf(1.0, 0.9)
.
Column {
val count = 10
val firstPagerState = rememberPagerState()
val secondPagerState = rememberPagerState()
val scrollingFollowingPair by remember {
derivedStateOf {
if (firstPagerState.isScrollInProgress) {
firstPagerState to secondPagerState
} else if (secondPagerState.isScrollInProgress) {
secondPagerState to firstPagerState
} else null
}
}
LaunchedEffect(scrollingFollowingPair) {
val (scrollingState, followingState) = scrollingFollowingPair ?: return@LaunchedEffect
snapshotFlow { scrollingState.currentPage + scrollingState.currentPageOffset }
.collect { pagePart ->
val divideAndRemainder = BigDecimal.valueOf(pagePart.toDouble())
.divideAndRemainder(BigDecimal.ONE)
followingState.scrollToPage(
divideAndRemainder[0].toInt(),
divideAndRemainder[1].toFloat(),
)
}
}
HorizontalPager(
count = count,
state = firstPagerState,
modifier = Modifier.weight(1f)
) {
Text(it.toString())
}
HorizontalPager(
count = count,
state = secondPagerState,
modifier = Modifier.weight(1f)
) {
Text(it.toString())
}
}
Result: