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:
But the text does not wrap, it eats up all the space in the Row:
@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?
Row
measures its children one after an other, and if some item needs to take all space available(e.g. if you use fillMaxWidth
, or in this case text that has more than one line), next items won't have any space left for them.
If it's layout logic supports compression up to zero size, you won't see it at all (like in case with the Icon
), otherwise it can be seen at the end of the row, actually taking zero size but being drawn outsize of the bounds.
To change order in which children are measured, you can use weight
modifier: in this case 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 behavior, pass false
to this parameter.
Row{
Text(text, modifier = Modifier.weight(1f))
IconButton(
onClick = { }
) {
Icon(
imageVector = Icons.Default.StarBorder,
null
)
}
}