5

I have a Row that has an icon button on the left, then 16dp padding, then a Text that takes up the remaining width in the Row, and finally on the right, another Text that should take up 25% of the width of the Row. Everything works except that the second Text is actually taking up 25% of the width of the Row, excluding the width of the icon button. This makes the second Text's width too thin.

I need the second Text to be exactly 25% of the entire Row's width because I have other Rows with Texts (not shown) that need to be aligned with this one.

So how do I make the IconButton's width actually be factored into the width of the second Text? Here's the simplified snippet:

Row(
    modifier = Modifier
        .padding(bottom = 16.dp)
        .fillMaxWidth()
        .background( color = Color(50, 50, 50) )
) {
    IconButton(
        modifier = Modifier
            .background(Color(100, 100, 100), CircleShape),
        onClick = { /* nothing */ }
    ) {
        Icon(Icons.Filled.Star,null, tint = Color(255, 192,0))
    }

    Text(
        modifier = Modifier
            .weight(1f) // Use weight 1f to take up remaining space
            .padding(start = 16.dp) // put left padding on the text: between the icon button & the text
            .background(color = Color(100, 100, 100)),
        text = "Remaining space",
        style = MaterialTheme.typography.bodyMedium
    )

    Text(
        text = "25%",
        modifier = Modifier
            .fillMaxWidth(0.25f) // Take up exactly 25% of the width
            .background(color = Color(150, 150, 150)),
        textAlign = TextAlign.Center,
        style = MaterialTheme.typography.bodyMedium
    )
}

Here's a (cropped) screenshot of the output: enter image description here

And a screenshot that proves that the second Text only takes up 25% of the Row's width excluding the IconButton's width (it looks like the second Text's width * 4 overlaps the IconButton by a couple of pixels, but in my code before I simplified it, there was no overlap so I don't think it's relevant):enter image description here

Initially, the icon button was in its own function, so I extracted it from the function. I've also tried setting the modifier.size() of the icon button instead of just using the default size. Both of these had no effect.

Expected result: the second Text takes up exactly 25% of the width of the icon button + padding + first Text + second Text.

Actual result: the second Text takes up exactly 25% of only the width of the padding + first Text + second Text.

1 Answer 1

2

You could wrap the IconButton and the first Text in an additional Row where you explicitly set the width to 75%:

Row(
    modifier = Modifier.fillMaxWidth(0.75f),
) {
    IconButton()

    Text(
        modifier = Modifier.weight(1f) // Use weight 1f to take up the remaining space
    )
}

Text(
    modifier = Modifier.fillMaxWidth() // Take up the remaining 25% of the parent's width
)

Then the second Text can take up the remaining 25%:

3
  • To the downvoter, I added a screenshot of the output to demonstrate that this actually solves the problem: "the second Text takes up exactly 25% of the width of the IconButton + padding + first Text + second Text.". There are definitely other (possibly superior) approaches, if you have a better one then feel free to post it as an answer instead of downvoting this one.
    – Leviathan
    Commented Jul 7 at 13:18
  • I didn't downvote, but can you explain why the approach by the OP didn't work? Is it not working because Compose just measures the Row children one after each other and thus once it reaches the fillMaxWidth(0.25f), it is already "too late"?
    – BenjyTec
    Commented Jul 8 at 6:30
  • Yes, that's basically right. The width(1f) of the first Text lets the remaining elements (without width) decide first on how big they want to be, only then will it take up all space that is left. The IconButton is measured first which only takes up as much space as needed. Then the second Text's fillMaxWidth(0.25f) takes 25% of what is left. That is 25% of the entire width minus the IconButton, as seen in op's screenshot.
    – Leviathan
    Commented Jul 8 at 7:15

Not the answer you're looking for? Browse other questions tagged or ask your own question.