Jetpack Compose とスタイル設定された string.xml

Nov 26 2022
問題 これで、strings.xml に HTML コンテンツを含むエントリができました: すべてのスタイリングがなくなりました! どうしたの?解決策 Jetpack Compose はスタイル付きテキストをまだサポートしていません。
Jetpack Compose のロゴ。見栄えは良いですが、スタイル付きのテキストはありません。何故ですか?

問題

したがって、strings.xml に HTML コンテンツを含むエントリがあります。

<string name="neatly_styled">Nice <u>underlined</u> and <b>bold</b> text.</string>

@Preview
@Compose
fun PreviewStyledText() {
  Text(text = stringResource(R.string.neatly_styled))
}

テキストのプレビュー。スタイリング不足!

スタイリングがすべてなくなりました!どうしたの?

解決

Jetpack Compose はスタイル付きテキストをまだサポートしていません。しかし、修正するのは簡単です。

問題139320238に続いて、独自の文字列リソース ローダーを作成します。

@Composable
fun annotatedStringResource(@StringRes id: Int): AnnotatedString {
    val resources = LocalContext.current.resources
    return remember(id) {
        val text = resources.getText(id)
        if (text is Spanned) {
            val spanStyles = mutableListOf<AnnotatedString.Range<SpanStyle>>()
            spanStyles.addAll(text.getSpans(0, text.length, UnderlineSpan::class.java).map {
                AnnotatedString.Range(
                    SpanStyle(textDecoration = TextDecoration.Underline),
                    text.getSpanStart(it),
                    text.getSpanEnd(it)
                )
            })
            spanStyles.addAll(text.getSpans(0, text.length, StyleSpan::class.java).map {
                AnnotatedString.Range(
                    SpanStyle(fontWeight = FontWeight.Bold),
                    text.getSpanStart(it),
                    text.getSpanEnd(it)
                )
            })
            AnnotatedString(text.toString(), spanStyles = spanStyles)
        } else {
            AnnotatedString(text.toString())
        }
    }
}

@Preview
@Composable
fun PreviewStyledTextFix() {
    Text(text = annotatedStringResource(R.string.styled_text))
}

テキストのプレビュー。プレビューではサポートされていないため、スタイリングはまだありません

ええと…まだスタイリングされていませんか?問題は、プレビュー モードもスタイル付きテキストをサポートしていないことです。

ただし、実際のデバイスは次のことを行います。

デバイスでのテキストのプレビュー。スタイリングあり!

また、ユーザーは実際のデバイスのみを使用するため、問題はありません。

フードの下

Jetpack Compose Text コンポーネントは、スタイル付きテキストをサポートしています。サポートは AnnotatedString と呼ばれます。したがって、Text に AnnotatedStrings を提供できれば問題ありません。

Android 側からは、ローカライズされた文字列を取得する 2 つの方法が提供されます。

  • String を返す String getString(id)。これにはスタイルを含めることはできず、HTML タグはドロップされて無視されます。
  • CharSequence を返す CharSequence getText(id)。注意点として、このシーケンスには HTML で定義されたスタイル スパンも含まれています。