6

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)
}
Gabriele Mariotti
  • 320,139
  • 94
  • 887
  • 841
nayan dhabarde
  • 1,734
  • 1
  • 19
  • 38

4 Answers4

12

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:

Phil Dukhov
  • 67,741
  • 15
  • 184
  • 220
2

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 = "")
}
devmike01
  • 1,971
  • 1
  • 20
  • 30
2

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

Pierre Vieira
  • 2,252
  • 4
  • 21
  • 41
  • Hi @Pierre Vieira, I think they should have exposed the modifier of RowScope which the Button component uses internally and it would have solved the problem without adding any further composables. One more thing, the Icon library it states in the documentation that it is a heavy library and only use if you are using a lot of icons from it – nayan dhabarde Sep 23 '21 at 06:38
1

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

Gabriele Mariotti
  • 320,139
  • 94
  • 887
  • 841