TL;DR
可変長のテキストに対してModifier.weight(1f)
を指定してください。
Row(modifier) {
Text(
text = text,
modifier = Modifier.weight(1f), // Or Modifier.weight(1f, fill = false)
)
Icon(
imageVector = Icons.Filled.CheckCircle,
contentDescription = "icon",
modifier = Modifier.size(48.dp)
)
}
左端にテキストがあり、右端には固定長のアイコンがあるRowを作りたいとします。(よくあるレイアウトですね)
これは次のように、Rowの子にSpacer(Modifier.weight(1f))
を追加したり、RowにhorizontalArrangement = Arrangement.SpaceBetween
を設定することで実装することができます。
@Composable
fun Row1(
text: String,
modifier: Modifier = Modifier,
) {
Row(modifier = modifier) {
Text(
text = text,
modifier = Modifier.border(1.dp, Color.Blue)
)
Spacer(Modifier.weight(1f))
Icon(
imageVector = Icons.Filled.CheckCircle,
contentDescription = "icon",
modifier = Modifier.size(48.dp)
)
}
}
@Composable
fun Row2(
text: String,
modifier: Modifier = Modifier,
) {
Row(
horizontalArrangement = Arrangement.SpaceBetween,
modifier = modifier,
) {
Text(
text = text,
modifier = Modifier.border(1.dp, Color.Blue)
)
Icon(
imageVector = Icons.Filled.CheckCircle,
contentDescription = "icon",
modifier = Modifier.size(48.dp)
)
}
}
一見すると良さそうに見えます。
Column(modifier) {
Row1(text = "text", modifier = Modifier.fillMaxWidth())
Row2(text = "text", modifier = Modifier.fillMaxWidth())
}
次のように長いテキストを設定した場合はどうなるでしょうか。
Column(modifier) {
Row1(text = "text".repeat(16), modifier = Modifier.fillMaxWidth())
Row2(text = "text".repeat(16), modifier = Modifier.fillMaxWidth())
}
アイコンが隠れてしまいました。今回は説明のために極端に長いテキストを用意しましたが、例えばユーザー設定でフォントサイズを大きくしたり、端末の横幅が小さい場合においても同じことが発生し得ます。
なぜこうなってしまうのか
横幅の計測順序が原因です。
- 長いテキストの幅を計測する (ここで既に画面が埋まってしまう)
- アイコンの幅を計測する
- 余った幅をSpacerで埋める(Row2の場合)
どうすればいいのか
次のように長いテキストに対してModifier.weight(1f)
を指定します。
Row(modifier) {
Text(
text = text,
modifier = Modifier
.weight(1f)
.border(1.dp, Color.Blue),
)
Icon(
imageVector = Icons.Filled.CheckCircle,
contentDescription = "icon",
modifier = Modifier.size(48.dp)
)
}
こう書いた場合、先にアイコンが計測され、余った幅を長いテキストが埋める形になるので、意図した通りに表示できます。
参考