How do I position ViewPager Indicator CenterHorizontally in JetPack Compose

1.5k Views Asked by At

I'm practicing ViewPager in JetPack compose which is experimental right now.

I was able to successfully make a basic view pager, but when trying to add an indicator, I get an error: Cannot access 'ColumnScopeInstance': it is internal in 'androidx.compose.foundation.layout'

Indicator code; (please keep in keep I already imported it) enter image description here

I tried looking for answers, I found a similar problem problem here on stackOverFlow, but I don't understand.

I also found out that I could only use horizontalAlignment = Alignment.CenterHorizontally in a column.

To ask bluntly, How do I position ViewPager Indicator Center Horizontally.

And I followed the procedure on the official document for pager indicator, I don't know what I'm missing.

I'm highly open to Ideas. Thanks to you in Advance. \If you details is needed I'm more than happy to provide.

2

There are 2 best solutions below

0
Mohammad Derakhshan On BEST ANSWER

alignment and arrangement depend on the parent's view. for example if you're using 'HorizontalPagerIndicator' inside of a box, you can use:

Box(contentAlignment = Alignment.Center) {....}

otherwise, if your parent view is Column, I suggest doing it this way:

 Column(
        modifier = ....,
        horizontalAlignment = Alignment.CenterHorizontally
 ) {...}

or for Row:

Row( 
    modifier = ....,
    horizontalArrangement = Arrangement.Center
) {...}
4
Thracian On

You can put your ViewPager and HorizontalPagerIndicator inside a box with contentAlignment = Alignment.Center/TopCenter/BottomCenter.

@Composable
private fun AlignmentSample() {
    Box(contentAlignment = Alignment.Center) {
        HorizontalPager(()
        HorizontalPagerIndicator()
    }
}

What i mean in the answer in the link you shared is some modifiers are unique to scopes of some Composables. For instance Modifier.align() is available is only inside Box. because of that you either need to place your content inside Box or you need to set a receiver to your @Composable argument such as

@Composable
private fun BoxScopeSample(
    modifier: Modifier = Modifier,
    content: @Composable BoxScope.() -> Unit
) {
    // You can't call content() here because it has BoxScope receiver
    Box(modifier) { // this here is BoxScope
        content()
    }
}

inside content lambda you can call Modifier.align() which is unique to BoxScope and use it as

BoxScopeSample(modifier = Modifier.size(200.dp).border(2.dp, Color.Cyan)) {
    Row(
        Modifier
            .align(Alignment.TopStart)
            .background(Color.Red)
            .size(100.dp)
    ) {

    }

    Row(
        Modifier
            .align(Alignment.BottomEnd)
            .background(Color.Green)
            .size(100.dp)
    ) {

    }
}

Which will look as

enter image description here

Then create another Composable with no scope such as

@Composable
private fun NonScopeSample(
    modifier: Modifier = Modifier,
    content: @Composable () -> Unit
) {

    Box(modifier) {
        content()
    }
}

And try calling

NonScopeSample(modifier = Modifier
    .size(200.dp)
    .border(2.dp, Color.Cyan)) {
    Row(
        Modifier
            .align(Alignment.TopStart)
            .background(Color.Red)
            .size(100.dp)
    ) {

    }

    Row(
        Modifier
            .align(Alignment.BottomEnd)
            .background(Color.Green)
            .size(100.dp)
    ) {

    }
}

you will get compile error because Modifier.align is not a generic Modifier as i mentioned above.