2

I am working on my first app fully designed by Compose.

I need to centralize vertically text with the Text() compose component. In traditional Android dev practice I did this over alignment property. Text() compose also has alignment property, but at this moment it has limited capacity (Alignment.Horizontal() is only allowed), despite on I noticed different alignment values within Text() when made a research in web. Similar case for Column() - it also has alignment property .wrapContentSize() and also has limitation on values that could be used here, despite on quick research in web shows it may receive CenterVertically too.

What is your way to achieve this visual effect? The full code piece is below

@ExperimentalUnitApi
@Composable
fun TripBookingContent(state: PassengerTripUiState.TripBookUiState) {
    Log.d(App.TAG, "[screen] TripBookingContent")
    val baselineGrid = dimensionResource(id = R.dimen.baseline_grid)
    val mainPadding = dimensionResource(id = R.dimen.main_margin_compact)
    var componentSpace = dimensionResource(id = R.dimen.component_space)
    Column(
        modifier = Modifier
            .wrapContentHeight()
            .fillMaxWidth()
            .padding(
                paddingValues = PaddingValues(
                    horizontal = mainPadding,
                    vertical = baselineGrid
                )
            )
    ) {
        TripViewItem(
            data = state.trip,
            {},
            modifier = Modifier.padding(vertical = baselineGrid)
        )
        Text(
            text = stringResource(id = R.string.booking_screen_driver),
            color = colorResource(id = R.color.white),
            style = TextStyle(textIndent = TextIndent(firstLine = TextUnit(16F, TextUnitType.Sp))),
            modifier = Modifier
                .height(componentSpace)
                .padding(start = baselineGrid)
                .fillMaxWidth()
                .background(color = colorResource(id = R.color.design_default_color_secondary_variant))
        )
        Log.d(App.TAG, "[state] state.driver - ${state}")
        Log.d(App.TAG, "[state] state.driver.toDriver() - ${state.driver}")
        DriverCardContent(data = state.driver)

        Text(
            text = stringResource(id = R.string.booking_screen_msg),
            color = colorResource(id = R.color.white),
            style = TextStyle(textIndent = TextIndent(firstLine = TextUnit(16F, TextUnitType.Sp))),
            textAlign = TextAlign.Center,
            modifier = Modifier
//                .height(componentSpace)
                .height(32.dp)
                .padding(start = baselineGrid)
                .fillMaxWidth()
                .background(color = colorResource(id = R.color.colorPrimaryDark))
        )
        /**
         * Disable book button at current (alfa version), for more details
         * */
        Button(
            onClick = { /* no op */ },
            modifier = Modifier
                .alpha(0F)
                .fillMaxWidth()
                .padding(baselineGrid)
                .height(dimensionResource(id = R.dimen.button_height)),
            colors = ButtonDefaults.buttonColors(
                backgroundColor = Color.Blue,
                contentColor = Color.White
            ),
        ) {
            Text(
                text = stringResource(id = R.string.booking_screen_confirm_button),
                modifier = Modifier.align(Alignment.CenterVertically),
                fontWeight = FontWeight.Bold
            )
        }
    }
}

UPDATE My final solution become this one below. I have to move padding and background to the Box() layer to achieve text in center both vertically and horizontally.

        Box(
            contentAlignment = Alignment.Center,
            modifier = Modifier
                .height(32.dp)
                .padding(start = baselineGrid)
                .fillMaxWidth()
                .background(color = colorResource(id = R.color.colorPrimaryDark))
        ) {
            Text(
                text = stringResource(id = R.string.booking_screen_msg),
                color = colorResource(id = R.color.white),
                style = TextStyle(textIndent = TextIndent(firstLine = TextUnit(16F, TextUnitType.Sp))),
                textAlign = TextAlign.Center,
/*                modifier = Modifier
//                .height(componentSpace)
                    .height(32.dp)
                    .padding(start = baselineGrid)
                    .fillMaxWidth()
                    .background(color = colorResource(id = R.color.colorPrimaryDark))*/
            )
        } 
Joe Dow
  • 100
  • 5

2 Answers2

2

It's not possible to center vertically only using Text(). I asked similar question here, you need to use Box() with contentAlignment = Alignment.Center. There are also CenterStart and CenterEnd options for alignment either.

   Box(
        contentAlignment = Alignment.Center,
    ) {
        Text(
            text = "Text",
            textAlign = TextAlign.Center
        )
    }
Thracian
  • 13,723
  • 7
  • 65
  • 116
  • Thank you for sharing. Is the Box the only option for this? Text(), Column() are misfit for this task, but what about Card() or some other component? – Joe Dow Jan 14 '22 at 09:24
  • 2
    If you click `Card`with cmd/crtl + click you will see that Card source is a `Surface` and Surface itself is also a Box with `contentAlignment: Alignment = Alignment.TopStart`. So it's possible with Box or you can create your own composable with `Layout`and use place according to your needs. I have tutorial about layouts and many other things if you are interested. – Thracian Jan 14 '22 at 09:32
  • 2
    With custom `Layout` and `Modifier` you can have your own alignment scheme like in this [image](https://github.com/SmartToolFactory/Jetpack-Compose-Tutorials/blob/master/screenshots/tutorial3_3_1.png) – Thracian Jan 14 '22 at 09:34
1

Alignment modifiers depend on the parent, which is how it supposed to be, in a vertical list (column) vertical alignment is handled by the parent (which is great that compose can enforce this)

Soo in your case you probably need a different hierarchy. For ex: Box instead of Column. Alternatively you can play around with the size of the Text, make it 200dp in height for example and use textAlign, to center it's text.

For reference:

  • Box(contentAlignment = Alignment.Center) -> Specifies alignment of children
  • Text(text = "example", modifier = Modifier.wrapContentSize().align()) -> Specifies alignment of Text composable under parent
  • Text(text = "example", textAlign = TextAlign.Center) -> specifies alignment of text, inside composable, using this with wrapContentSize() won't have any effect, since the Composable has the same size as it's content text
Róbert Nagy
  • 5,058
  • 18
  • 39