Jetpack Compose e stilizza strings.xml

Nov 26 2022
Problema Quindi hai una voce in strings.xml con contenuto HTML: tutto lo stile è sparito! Cosa è successo? Soluzione Jetpack Compose non supporta ancora il testo con stile.
Jetpack componi il logo. Sembra carino, ma non ha testo in stile. Perché?

Problema

Quindi hai una voce in strings.xml con contenuto 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))
}

Anteprima del testo. Manca lo stile!

Tutto lo stile è sparito! Cosa è successo?

Soluzione

Jetpack Compose non supporta ancora il testo con stile. Ma è semplice da risolvere.

A seguito del problema 139320238 , creiamo il nostro caricatore di risorse di stringa:

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

Anteprima del testo. Ancora nessuno stile, perché non è supportato in Anteprima

Eh cosa... Ancora NON IN STILE? Il fatto è che la modalità Anteprima non supporta neanche il testo in stile.

Ma un vero dispositivo fa:

Anteprima del testo su un dispositivo. Lo stile è lì!

E poiché i nostri utenti utilizzano solo dispositivi reali, stiamo tutti bene.

Sotto il cappuccio

Il componente Jetpack Compose Text supporta il testo con stile. Il supporto si chiama AnnotatedString. Quindi, se possiamo solo fornire Text con AnnotatedStrings, stiamo tutti bene.

Dal lato Android, fornisce due modi per ottenere una stringa localizzata:

  • String getString(id), che restituisce una stringa. Questo non può contenere alcuno stile e i tag HTML vengono semplicemente eliminati e ignorati.
  • CharSequence getText(id), che restituisce una CharSequence. Il problema è che questa sequenza contiene anche gli intervalli di stile definiti in HTML.