displayname
displayname

Reputation: 53

Nested HorizontalPager in Jetpack Compose

I have a top level HorizontalPager, its pages can be just a single page composable or they can be another HorizontalPager. When the inner HorizontalPager can swipe pages in the direction of the user interaction, it should consume that interaction, and when it reaches the end the outer HorizontalPager should change to another page.

By default, without any kind of modifier, this almost works, but some times the inner scroll won't work or starts working while the top level HorizontalPager is swiping pages. So de UX is not consistent.

What would be the right approach to make this work? I've been trying to use Modifier.pointerInput and Modifier.pointerInteropFilter, but it seems that HorizontalPager internals can take over no matter what I do. I also tried using Modifier.nestedScroll without much success.

Example of what I am trying to achieve.

@OptIn(ExperimentalFoundationApi::class)
@Composable
fun CustomPager() {
   val pagerState = rememberPagerState(pageCount = {
       10
   })

   // top level HorizontalPager
   HorizontalPager(
       state = pagerState,
       modifier = Modifier.fillMaxSize(),
       pageSpacing = 10.dp,
   ) { itemIndex ->
        InnerPager()
   }
}

@OptIn(ExperimentalFoundationApi::class)
@Composable
fun InnerPager() {
    val pagerState = rememberPagerState(pageCount = {
        3
    })

    CompositionLocalProvider(
       LocalOverscrollConfiguration provides null,
    ) {
        HorizontalPager(
            state = pagerState,
            modifier = Modifier.fillMaxSize(),
            pageSpacing = 0.dp,
        ) { itemIndex ->
            Page()
        }
    }
}

@Composable
fun Page() {
    val color = Color(0xFF000000.toInt() + (0x00FFFFFF * Math.random()).toInt())

    Surface(
        modifier = Modifier.fillMaxSize(),
        color = color,
    ) {
    }
}

@Preview
@Composable
fun CustomPagerPreview() {
    CustomPager()
}

One scenario where this doesn't work is after swiping all the pages from a child HorizontalPager, the parent pager will start swiping, but then if you swipe again you can skip completely the next child HorizontalPager without swiping through all its pages.

Upvotes: 1

Views: 411

Answers (0)

Related Questions