Home > Software engineering >  Compose: wrap text in Row layout, instead of pushing siblings out
Compose: wrap text in Row layout, instead of pushing siblings out

Time:09-17

I'm dipping my toes into Jetpack Compose, but I'm stumped by the behaviour of Row. I have a text next to an icon button, and I want the icon button to be anchored to the side with a minimum width of 48dp, and have text wrap around it. Like this:

Layout goal

But the text does not wrap, it eats up all the space in the Row:

Layout previews

@Composable
fun SampleLayout(text: String) {
                    Row(
                        modifier = Modifier.fillMaxWidth(),
                        horizontalArrangement = Arrangement.SpaceBetween,
                    ) {
                        Text(text)
                        IconButton(
                            onClick = {  },
                        ) {
                            Icon(
                                imageVector = androidx.compose.material.icons.Icons.Default.StarBorder,
                                null
                            )
                        }
                    }
}

@Preview(showBackground = true, backgroundColor = 0x006EAEA0, fontScale = 1.5F)
@Composable
fun SamplePreview1() {
    Box(Modifier.padding(16.dp)) {
        SampleLayout("helooooo")
    }
}

@Preview(showBackground = true, backgroundColor = 0x006EAEA0, fontScale = 1.5F)
@Composable
fun SamplePreview2() {
    Box(Modifier.padding(16.dp)) {
        SampleLayout("helooooooooooooooooooooooooooo")
    }
}
@Preview(showBackground = true, backgroundColor = 0x006EAEA0, fontScale = 1.5F)
@Composable
fun SamplePreview3() {
    Box(Modifier.padding(16.dp)) {
        SampleLayout("heloooooooooooooooooooooooooooooooooooooooo")
    }
}

I've tried setting the minimum width of the icon 48dp, but the text then still fills until the end of the row.

How can I make sure the the Text width does not go further than the icon button?

CodePudding user response:

By default Text has a higher layout priority than Icon in order to fill the necessary space. You can change this with the weight modifier.

After using this modifier, the size of Icon will be calculated before Text:

The parent will divide the vertical space remaining after measuring unweighted child elements

Also weight has a fill parameter, which is set to true by default. This is equivalent to fillMaxWidth (when weight is used inside a Row), so you can skip the fillMaxWidth modifier in your parent. When you don't need this behaviour, pass false to this parameter.

Row(
    horizontalArrangement = Arrangement.SpaceBetween,
) {
    Text(text, modifier = Modifier.weight(1f))
    IconButton(
        onClick = { }
    ) {
        Icon(
            imageVector = Icons.Default.StarBorder,
            null
        )
    }
}

CodePudding user response:

Try this

@Composable
fun SampleLayout(text: String) {
                    Row(
                        modifier = Modifier.fillMaxWidth(),
                        horizontalArrangement = Arrangement.SpaceBetween,
                    ) {
                        Text(text = text)
                        IconButton(
                            modifier = Modifier.weight(1f, fill = false), //You must add the false fill here to keep it from occupying all the available space
                            onClick = {  },
                        ) {
                            Icon(
                                imageVector = androidx.compose.material.icons.Icons.Default.StarBorder,
                                null
                            )
                        }
                    }
}
  • Related