LoginSignup
0
0

可変長のテキストを含むRowではSpacer(Modifier.weight(1f))やArrangement.SpaceBetweenと指定してはいけない

Last updated at Posted at 2023-08-09

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)
    )
}

image.png

左端にテキストがあり、右端には固定長のアイコンがあるRowを作りたいとします。(よくあるレイアウトですね)
image.png

これは次のように、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())
}

image.png

次のように長いテキストを設定した場合はどうなるでしょうか。

Column(modifier) {
    Row1(text = "text".repeat(16), modifier = Modifier.fillMaxWidth())
    Row2(text = "text".repeat(16), modifier = Modifier.fillMaxWidth())
}

image.png

アイコンが隠れてしまいました。今回は説明のために極端に長いテキストを用意しましたが、例えばユーザー設定でフォントサイズを大きくしたり、端末の横幅が小さい場合においても同じことが発生し得ます。

なぜこうなってしまうのか

横幅の計測順序が原因です。

  1. 長いテキストの幅を計測する (ここで既に画面が埋まってしまう)
  2. アイコンの幅を計測する
  3. 余った幅を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)
    )
}

こう書いた場合、先にアイコンが計測され、余った幅を長いテキストが埋める形になるので、意図した通りに表示できます。
image.png

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0