Jetpack Compose и стилизованный файл strings.xml

Проблема
Итак, у вас есть запись в 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 он предоставляет два способа получить локализованную строку:
- Строка getString(id), которая возвращает строку. Это не может содержать никаких стилей, а теги HTML просто удаляются и игнорируются.
- CharSequence getText(id), который возвращает CharSequence. Загвоздка в том, что эта последовательность также содержит диапазоны стилей, определенные в HTML.