🎨

Jetpack Composeでテキストに色をつける

2022/03/20に公開

はじめに

Jetpack ComposeでText Composableに色を付加しています。 条件に応じてスタイルを変更する例を示します。

シンプルな例

Compose のテキスト  |  Jetpack Compose  |  Android Developers に記載がある通り、SpanStyleを使うことで各文字ごとにスタイルを適用させることが出来ます。

@Composable
fun MultipleStylesInText() {
    Text(
        buildAnnotatedString {
            withStyle(style = SpanStyle(color = Color.Blue)) {
                append("H")
            }
            append("ello ")

            withStyle(style = SpanStyle(fontWeight = FontWeight.Bold, color = Color.Red)) {
                append("W")
            }
            append("orld")
        }
    )
}

条件分岐する例

1文字ずつ手入力でスタイルを組み立てる必要はなく、関数化して文字列を渡して条件ごとに分岐してスタイルを決めるようなことも出来ます。
下記コードではRGBの文字をそれぞれ赤緑青に変更する例です。

@Composable
fun ColorizedText(text: String, modifier: Modifier = Modifier) {
    Text(
        buildAnnotatedString {
            text.forEach { c ->
                when (c) {
                    'R' -> withStyle(SpanStyle(color = Color.Red)) {
                        append(c)
                    }
                    'G' -> withStyle(SpanStyle(color = Color.Green)) {
                        append(c)
                    }
                    'B' -> withStyle(SpanStyle(color = Color.Blue)) {
                        append(c)
                    }
                    else -> append(c)
                }
            }
        },
        modifier = modifier
    )
}

状態を持たせて条件分岐する例

変数の値を内部で持ってそれに応じて条件分岐することも出来ます。
以下コードは対応する中括弧に色をつける例です。

@Composable
fun ColorizedBracketsText(text: String, modifier: Modifier = Modifier) {
    var colorIndex = 0
    val rainbowColors = listOf(
        Color(0xFFF1442D),
        Color(0xFFF58F00),
        Color(0xFFF1C521),
        Color(0xFF3AB441),
        Color(0xFF1E6CD5),
        Color(0xFF5C239E),
    ).shuffled()
    val len = rainbowColors.size
    Text(
        buildAnnotatedString {
            text.forEach { c ->
                when (c) {
                    '{' -> withStyle(
                        SpanStyle(
                            color = rainbowColors[colorIndex % len],
                            fontWeight = FontWeight.Bold
                        )
                    ) {
                        append(c)
                        colorIndex = (colorIndex + 1) % len
                    }
                    '}' -> withStyle(
                        SpanStyle(
                            color = rainbowColors[(colorIndex - 1 + len) % len],
                            fontWeight = FontWeight.Bold
                        )
                    ) {
                        colorIndex = (colorIndex - 1 + len) % len
                        append(c)
                    }
                    else -> append(c)
                }
            }
        }, modifier = modifier
    )
}

実際にRGBの各文字に色を与えるソースコードに適用した場合は以下のように見えます。

中括弧が開いて閉じてを繰り返す所で色が変わっていない点に関しては色をランダムに生成してスタックに積んだり降ろしたりとした方が良かったかもしれません。

参考

Discussion