Search code examples
androidandroid-jetpack-composeandroid-jetpack-compose-listjetpack-compose-accompanistandroid-jetpack-compose-pager

Jetpack Compose - HorizontalPager item spacing/padding for items with max width


Using Jetpack Compose and the accompanist pager, I'm trying to create a HorizontalPager where:

  1. Edges of items to the left and right of current item are shown
  2. There is a max width to the Pager items

As an example, I wrote the following code (for simplicities sake, I made Text items, but in reality, I'm actually making more complex Card items):

@Composable
fun MyText(modifier: Modifier) {
  Text(
    text = LOREM_IPSUM_TEXT,
    modifier = modifier
      .wrapContentHeight()
      .border(BorderStroke(1.dp, Color.Red))
  )
}

@ExperimentalPagerApi
@Composable
fun MyPager(pagerItem: @Composable () -> Unit = {}) {
  Scaffold {
    Column(
      modifier = Modifier
        .fillMaxSize()
        // In case items in the VP are taller than the screen -> scrollable
        .verticalScroll(rememberScrollState())
    ) {
      HorizontalPager(
        contentPadding = PaddingValues(32.dp),
        itemSpacing = 16.dp,
        count = 3,
      ) {
        pagerItem()
      }
    }
  }
}

@ExperimentalPagerApi
@Preview
@Composable
fun MyPager_200dpWidth() {
  MyPager { MyText(modifier = Modifier.widthIn(max = 200.dp)) }
}

@ExperimentalPagerApi
@Preview
@Composable
fun MyPager_500dpWidth() {
  MyPager { MyText(modifier = Modifier.widthIn(max = 500.dp)) }
}

@ExperimentalPagerApi
@Preview
@Composable
fun MyPager_FillMaxWidth() {
  MyPager { MyText(modifier = Modifier.fillMaxWidth()) }
}

The issue I'm having is that when I make the item have a max width that seems to be smaller than the screen width (see MyPager_200dpWidth), I no longer see the items on the side anymore. On the other hand, using items with larger max widths (See MyPager_500dpWidth) or fillMaxWidth (See MyPager_FillMaxWidth) allows me to see the items on the side.

It seems weird to me that items with the smaller max width are actually taking up more horizontal space than the items with the larger max width. This can be shown in the Preview section...

Preview Comparison

See how the images on the left (MyPager_500dpWidth) and middle (MyPager_FillMaxWidth) show the next item, while the image on the right (MyPager_200dpWidth`) takes up the whole screen? Here's another comparison when hovering my mouse over the items to see the skeleton boxes...

Preview Comparison with skeleton

Just wondering if someone could help me figure out how I can solve this use case. Is it possible that there's a bug in Compose?


Solution

  • The page size is controlled by the HorizontalPager.contentPadding parameter.

    Applying widthIn(max = 200.dp) to your text only reduces the size of your element inside the page, while the page size remains unchanged.

    Applying more padding should solve your problem, for example, contentPadding = PaddingValues(100.dp) looks like this: