How to align different elements inside a Button in Jetpack Compose?

9.4k views Asked by At

I am trying to build the following component,

enter image description here

Following is my code,

Button(onClick = { /*TODO*/ }, modifier = Modifier.fillMaxWidth()) {
    Image(painter = painterResource(id = R.drawable.ic_check_circle) , contentDescription = "")
    Text(text = "John Doe", textAlign = TextAlign.Start)
    Image(painter = painterResource(id = R.drawable.ic_arrow_forward), contentDescription = "",
        alignment = Alignment.TopEnd)
}
4

There are 4 answers

0
Phil Dukhov On BEST ANSWER

You can use Spacer:

  1. Modifier.width(10.dp) will give you static size.

  2. Modifier.weight(1f)) will fill all available space.

Button(onClick = { /*TODO*/ }, modifier = Modifier.fillMaxWidth()) {
    Image(painter = painterResource(id = R.drawable.ic_undo) , contentDescription = "")
    Spacer(modifier = Modifier.width(10.dp))
    Text(text = "John Doe")
    Spacer(modifier = Modifier.weight(1f))
    Image(painter = painterResource(id = R.drawable.ic_redo), contentDescription = "")
}

Result:

1
Pierre Vieira On

I made an alternative that closely matches your layout using ConstraintLayout.

Put in your build.gradle file (module scope inside) inside dependencies:

// To use constraint layout in compose
implementation "androidx.constraintlayout:constraintlayout-compose:1.0.0-beta02"

NOTE: I'm using icons provided by android studio itself, remember to use yours if they are custom icons. To do this just change the id parameter of painterResource referring to the appropriate drawables.

In your compose function that displays the button, use the following code:

Button(
    modifier = Modifier
        .fillMaxWidth(),
    shape = RoundedCornerShape(50),
    colors = ButtonDefaults.buttonColors(
        backgroundColor = Color(0xFF847EBA),
        contentColor = Color.White
    ),
    contentPadding = PaddingValues(horizontal = 4.dp),
    onClick = {}
) {
    ConstraintLayout(modifier = Modifier.fillMaxWidth()) {
        val (startIcon, text, endIcon) = createRefs()
        Image(
            modifier = Modifier.constrainAs(startIcon) {
                start.linkTo(parent.start)
            },
            painter = painterResource(id = R.drawable.ic_check_circle_outline),
            contentDescription = null
        )
        Text(
            modifier = Modifier.constrainAs(text) {
                start.linkTo(startIcon.end, margin = 8.dp)
                bottom.linkTo(parent.bottom)
                top.linkTo(parent.top)
            },
            text = "John Doe"
        )
        Image(
            modifier = Modifier.constrainAs(endIcon) {
                end.linkTo(parent.end)
            },
            painter = painterResource(id = R.drawable.ic_navigate_next),
            contentDescription = null
        )
    }
}

Visual effect:

personalized button using constraint layout to align children

0
devmike01 On

Wrap the components inside your button compose function with a Row and set the horizontalArrangement to Arrangement.SpaceBetween. See the modified version of your code snippet below.

       Button(onClick = { /*TODO*/ }, modifier = Modifier.fillMaxWidth()) {
    Row(modifier = Modifier
        .align(alignment = Alignment.CenterVertically)
        .fillMaxWidth(0.9f)) {
        Image(painter = painterResource(id = R.drawable.ic_baseline_subject_24),
            contentDescription = "", alignment = Alignment.CenterStart)
        Spacer(modifier = Modifier.width(10.dp))
        Text(text = "John Doe", textAlign = TextAlign.Start, modifier = Modifier.align(alignment = Alignment.CenterVertically))
    }
    Image(painter = painterResource(id = R.drawable.ic_baseline_subject_24),
        contentDescription = "")
}
0
Gabriele Mariotti On

The content of the Button is a RowScope.
Just apply the weight modifier to the Text composable:

Button(onClick = { /*TODO*/ }, modifier = Modifier.fillMaxWidth()) {
    Image()
    Spacer(modifier = Modifier.width(10.dp))
    Text(text = "John Doe",modifier = Modifier.weight(1f))
    Image()
}

enter image description here