Risorse stringa

Una risorsa stringa fornisce stringhe di testo per l'applicazione, oltre a formattazione e stile del testo. Esistono tre tipi di risorse che possono fornire stringhe all'applicazione:

String
Risorsa XML che fornisce una singola stringa.
Array di stringhe
Risorsa XML che fornisce un array di stringhe.
Stringhe relative alla quantità (plurali)
Risorsa XML che trasporta stringhe diverse per il pluralizzazione.

Tutte le stringhe sono in grado di applicare alcuni markup di stile e argomenti di formattazione. Per informazioni sull'applicazione di stili e formattazione alle stringhe, consulta la sezione Formattazione e stili.

Stringa

Una singola stringa a cui è possibile fare riferimento dall'applicazione o da altri file di risorse (ad esempio, un layout XML).

Nota: una stringa è una risorsa semplice a cui viene fatto riferimento utilizzando il valore fornito nell'attributo name (non il nome del file XML). Quindi, puoi combinare risorse stringa con altre risorse semplici in un unico file XML, in un unico elemento <resources>.

percorso file:
res/values/filename.xml
Il nome del file è arbitrario. L'elemento name dell'elemento <string> viene utilizzato come ID risorsa.
tipo di dati della risorsa compilata:
Puntatore di risorsa a un String.
riferimento risorsa:
In Java: R.string.string_name
In XML:@string/string_name
:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string
        name="string_name"
        >text_string</string>
</resources>
:
<resources>
Obbligatorio. Questo deve essere il nodo radice.

Nessun attributo.

<string>
Una stringa, che può includere l'applicazione di stili ai tag. Ricorda che devi eseguire l'escape di apostrofi e virgolette. Per ulteriori informazioni su come definire correttamente lo stile e la formattazione delle stringhe, consulta la sezione Formattazione e stili di seguito.

:

name
Stringa. Un nome per la stringa. Questo nome viene utilizzato come ID risorsa.
esempio:
File XML salvato in res/values/strings.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="hello">Hello!</string>
</resources>

Questo XML di layout applica una stringa a una vista:

<TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="@string/hello" />

Questo codice dell'applicazione recupera una stringa:

Kotlin

val string: String = getString(R.string.hello)

Java

String string = getString(R.string.hello);

Puoi utilizzare getString(int) o getText(int) per recuperare una stringa. getText(int) conserva gli stili RTF applicati alla stringa.

Array di stringhe

Un array di stringhe a cui è possibile fare riferimento dall'applicazione.

Nota: un array di stringhe è una risorsa semplice a cui viene fatto riferimento utilizzando il valore fornito nell'attributo name (non il nome del file XML). Di conseguenza, puoi combinare le risorse di array di stringhe con altre risorse semplici in un unico file XML, in un unico elemento <resources>.

percorso file:
res/values/filename.xml
Il nome del file è arbitrario. L'elemento name dell'elemento <string-array> viene utilizzato come ID risorsa.
tipo di dati della risorsa compilata:
Puntatore di risorsa a un array di String.
riferimento risorsa:
In Java: R.array.string_array_name
In XML: @[package:]array/string_array_name
:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array
        name="string_array_name">
        <item
            >text_string</item>
    </string-array>
</resources>
:
<resources>
Obbligatorio. Questo deve essere il nodo radice.

Nessun attributo.

<string-array>
Definisce un array di stringhe. Contiene uno o più elementi <item>.

:

name
Stringa. Il nome dell'array. Questo nome viene utilizzato come ID risorsa per fare riferimento all'array.
<item>
Una stringa, che può includere l'applicazione di stili ai tag. Il valore può essere un riferimento a un'altra risorsa stringa. Deve essere un elemento secondario di un elemento <string-array>. Ricorda che devi eseguire l'escape di apostrofi e virgolette. Consulta la sezione Formattazione e stili di seguito per informazioni su come applicare uno stile e formattare correttamente le stringhe.

Nessun attributo.

esempio:
File XML salvato in res/values/strings.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="planets_array">
        <item>Mercury</item>
        <item>Venus</item>
        <item>Earth</item>
        <item>Mars</item>
    </string-array>
</resources>

Questo codice applicazione recupera un array di stringhe:

Kotlin

val array: Array<String> = resources.getStringArray(R.array.planets_array)

Java

Resources res = getResources();
String[] planets = res.getStringArray(R.array.planets_array);

Stringhe relative alla quantità (plurale)

Ogni lingua ha regole differenti sull'accordo grammaticale con la quantità. In inglese, ad esempio, la quantità 1 è un caso speciale. Scriviamo "1 libro", ma per qualsiasi altra quantità scriveremmo "n libri". Questa distinzione tra singolare e plurale è molto comune, ma altre lingue fanno distinzioni più precise. Il set completo supportato da Android è zero, one, two, few, many e other.

Le regole per decidere quale caso utilizzare per una determinata lingua e quantità possono essere molto complesse, quindi Android ti offre metodi come getQuantityString() per selezionare la risorsa appropriata per te.

Anche se storicamente vengono chiamate "stringhe di quantità" (e continuano a essere chiamate nell'API), le stringhe di quantità devono essere utilizzate solo per i plurali. Sarebbe un errore utilizzare le stringhe di quantità per implementare qualcosa come "Posta in arrivo" di Gmail invece di "Posta in arrivo (12)" quando ci sono messaggi da leggere, ad esempio. Potrebbe sembrare pratico utilizzare stringhe di quantità al posto di un'istruzione if, ma è importante tenere presente che alcune lingue (come il cinese) non fanno nessuna distinzione grammaticale, quindi otterrai sempre la stringa other.

La scelta della stringa da utilizzare si basa esclusivamente sulla necessità grammaticale. In inglese, una stringa per zero viene ignorata anche se la quantità è 0, perché 0 non è grammaticalmente diverso da 2 o da qualsiasi altro numero tranne 1 ("zero libri", "un libro", "due libri" e così via). Al contrario, in coreano viene utilizzata solo la stringa other.

Non farti ingannare dal fatto che, ad esempio, two sembra che possa applicarsi solo alla quantità 2: una lingua può richiedere che 2, 12, 102 (e così via) vengano tutti trattati come l'uno ma in modo diverso rispetto ad altre quantità. Affidati al traduttore per capire su quali differenze insiste la lingua.

Se il messaggio non contiene il numero di quantità, probabilmente non è un buon candidato per il plurale. Ad esempio, in lituano la forma singolare viene utilizzata sia per 1 che per 101, quindi "1 libro" viene tradotto come "1 knyga" e "101 libri" viene tradotto come "101 knyga". Al contrario "un libro" è "knyga" e "molti libri" è "daug knygpiù". Se un messaggio plurale in inglese contiene "un libro" (singolare) e "molti libri" (plurale) senza il numero effettivo, può essere tradotto come "knyga" (un libro)/"daug knygpiù" (molti libri), ma con le regole lituane verrà mostrato "knyga" (un libro singolo), quando il numero è 101.

Spesso è possibile evitare stringhe di quantità utilizzando formule prive di quantità, come "Libri: 1". Se ritieni che si tratti di uno stile accettabile per la tua candidatura, questo semplifica la tua vita e quella dei traduttori.

Con l'API 24 o versioni successive, puoi utilizzare invece la classe ICU MessageFormat molto più potente.

Nota: una raccolta plurali è una risorsa semplice a cui viene fatto riferimento tramite il valore fornito nell'attributo name (non il nome del file XML). Di conseguenza, puoi combinare risorse plurali con altre risorse semplici in un unico file XML, in un unico elemento <resources>.

percorso file:
res/values/filename.xml
Il nome del file è arbitrario. L'elemento name dell'elemento <plurals> viene utilizzato come ID risorsa.
riferimento risorsa:
In Java: R.plurals.plural_name
:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <plurals
        name="plural_name">
        <item
            quantity=["zero" | "one" | "two" | "few" | "many" | "other"]
            >text_string</item>
    </plurals>
</resources>
:
<resources>
Obbligatorio. Questo deve essere il nodo radice.

Nessun attributo.

<plurals>
Una raccolta di stringhe, di cui viene fornita una stringa a seconda della quantità di qualcosa. Contiene uno o più elementi <item>.

:

name
Stringa. Il nome della coppia di stringhe. Questo nome viene utilizzato come ID risorsa.
<item>
Una stringa plurale o singolare. Il valore può essere un riferimento a un'altra risorsa stringa. Deve essere un elemento secondario di un elemento <plurals>. Ricorda di utilizzare l'escape di apostrofi e virgolette. Consulta la sezione Formattazione e stile di seguito per informazioni su come applicare correttamente lo stile e la formattazione delle stringhe.

:

quantity
Parola chiave. Un valore che indica quando utilizzare questa stringa. Valori validi, con esempi non esaustivi tra parentesi:
ValoreDescrizione
zeroQuando la lingua richiede un trattamento speciale del numero 0 (come in arabo).
oneQuando la lingua richiede un trattamento speciale dei numeri come uno (come per il numero 1 in inglese e per la maggior parte delle altre lingue; in russo, qualsiasi numero che termina con 1 ma non termina con 11 è in questo corso).
twoQuando la lingua richiede un trattamento speciale dei numeri come due (come con 2 in gallese o 102 in sloveno).
fewQuando la lingua richiede un trattamento speciale per i numeri "piccoli" (come con 2, 3 e 4 in ceco; o per i numeri che terminano con 2, 3 o 4 ma non 12, 13 o 14 in polacco).
manyQuando la lingua richiede un trattamento speciale per i numeri "grandi" (come i numeri che terminano 11-99 in maltese).
otherQuando la lingua non richiede un trattamento speciale della quantità specificata (come con tutti i numeri in cinese o 42 in inglese).
esempio:
File XML salvato in res/values/strings.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <plurals name="numberOfSongsAvailable">
        <!--
             As a developer, you should always supply "one" and "other"
             strings. Your translators will know which strings are actually
             needed for their language. Always include %d in "one" because
             translators will need to use %d for languages where "one"
             doesn't mean 1 (as explained above).
          -->
        <item quantity="one">%d song found.</item>
        <item quantity="other">%d songs found.</item>
    </plurals>
</resources>

File XML salvato all'indirizzo res/values-pl/strings.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <plurals name="numberOfSongsAvailable">
        <item quantity="one">Znaleziono %d piosenkę.</item>
        <item quantity="few">Znaleziono %d piosenki.</item>
        <item quantity="other">Znaleziono %d piosenek.</item>
    </plurals>
</resources>

Uso:

Kotlin

val count = getNumberOfSongsAvailable()
val songsFound = resources.getQuantityString(R.plurals.numberOfSongsAvailable, count, count)

Java

int count = getNumberOfSongsAvailable();
Resources res = getResources();
String songsFound = res.getQuantityString(R.plurals.numberOfSongsAvailable, count, count);

Quando utilizzi il metodo getQuantityString(), devi passare due volte il comando count se la stringa include la formattazione delle stringhe con un numero. Ad esempio, per la stringa %d songs found, il primo parametro count seleziona la stringa plurale appropriata e il secondo parametro count viene inserito nel segnaposto %d. Se le stringhe plurali non includono la formattazione delle stringhe, non è necessario trasmettere il terzo parametro a getQuantityString.

Formato e stile

Ecco alcuni aspetti importanti da sapere su come formattare e applicare correttamente lo stile delle risorse delle stringhe.

Gestire i caratteri speciali

Quando una stringa contiene caratteri speciali in XML, devi eseguire l'escape dei caratteri in base alle regole di escape XML/HTML standard. Se devi eseguire l'escape di un carattere che ha un significato speciale in Android, devi utilizzare una barra rovesciata precedente.

Per impostazione predefinita, Android comprimerà le sequenze di spazi vuoti in un unico spazio. Per evitarlo, racchiudi la parte pertinente della stringa tra virgolette. In questo caso, tutti gli spazi (incluse le nuove righe) verranno mantenuti all'interno dell'area tra virgolette. Le virgolette doppie consentono di utilizzare anche le normali virgolette singole senza caratteri di escape.

Carattere Moduli con caratteri di escape
@ \@
? \?
Nuova riga \n
Tab \t
U+XXXX carattere Unicode \uXXXX
Virgoletta singola (')

Una qualsiasi delle seguenti opzioni:

  • \'
  • Racchiudi l'intera stringa tra virgolette doppie (ad esempio "This'll work")
Virgolette doppie (") \"

Ricorda che racchiudere la stringa tra virgolette singole non funziona.

Il comprimimento degli spazi e l'escape di Android si verificano dopo che il file delle risorse viene analizzato come XML. Ciò significa che gli elementi <string> &#32; &#8200; &#8195;</string> (spazio, punteggiatura, spazio Unicode Em) vengono tutti compressi in un singolo spazio (" "), perché sono tutti spazi Unicode dopo che il file viene analizzato come XML. Per mantenere questi spazi così come sono, puoi citarli (<string>" &#32; &#8200; &#8195;"</string>) o utilizzare l'escape di Android (<string> \u0032 \u8200 \u8195</string>).

Nota: dal punto di vista del parser XML, non esiste alcuna differenza tra <string>"Test this"</string> e <string>&quot;Test this&quot;</string>. Entrambi i moduli non mostreranno le virgolette, ma attiveranno le citazioni di Android che preservano lo spazio vuoto (che non avranno effetto pratico in questo caso).

Stringhe di formattazione

Se devi formattare le stringhe, puoi farlo inserendo gli argomenti del formato nella risorsa della stringa, come dimostrato dalla seguente risorsa di esempio.

<string name="welcome_messages">Hello, %1$s! You have %2$d new messages.</string>

In questo esempio, la stringa del formato ha due argomenti: %1$s è una stringa e %2$d è un numero decimale. Quindi, formatta la stringa chiamando getString(int, Object...). Ecco alcuni esempi:

Kotlin

var text = getString(R.string.welcome_messages, username, mailCount)

Java

String text = getString(R.string.welcome_messages, username, mailCount);

Stile con il markup HTML

Puoi aggiungere stili alle stringhe con il markup HTML. Ecco alcuni esempi:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="welcome">Welcome to <b>Android</b>!</string>
</resources>

Sono supportati i seguenti elementi HTML:

  • Grassetto: <b>
  • Corsivo: <i>, <cite>, <signal>, <em>
  • Testo più grande del 25%: <big>
  • Testo più piccolo del 20%: <small>
  • Impostazione delle proprietà dei caratteri: <font face=”font_family“ color=”hex_color”>. Esempi di possibili famiglie di caratteri includono monospace, serif e sans_serif.
  • Impostazione di una famiglia di caratteri monospazio: <tt>
  • Testo barrato: <s>, <strike>, <del>
  • Sottolineato: <u>
  • Apice: <sup>
  • Pedice: <sub>
  • Elenchi puntati: <ul>, <li>
  • Interruzioni di riga: <br>
  • Divisione: <div>
  • Stile CSS: <span style=”color|background_color|text-decoration”>
  • Paragrafi: <p dir="rtl | ltr" style="...".

Se non applichi la formattazione, puoi impostare il testo di TextView direttamente chiamando setText(java.lang.CharSequence). In alcuni casi, tuttavia, potresti voler creare una risorsa di testo con stili utilizzata anche come stringa di formato. Normalmente, questo non funziona perché i metodi format(String, Object...) e getString(int, Object...) rimuoveno tutte le informazioni sullo stile dalla stringa. La soluzione consiste nello scrivere i tag HTML con entità di escape, che vengono recuperati con fromHtml(String), dopo la formattazione. Ecco alcuni esempi:

  1. Memorizza la risorsa di testo con stile come stringa con caratteri di escape HTML:
    <resources>
      <string name="welcome_messages">Hello, %1$s! You have &lt;b>%2$d new messages&lt;/b>.</string>
    </resources>
    

    In questa stringa formattata, viene aggiunto un elemento <b>. Nota che la parentesi aperta presenta caratteri di escape HTML, utilizzando la notazione &lt;.

  2. Quindi formatta la stringa come al solito, ma chiama anche fromHtml(String) per convertire il testo HTML in testo con stile:

    Kotlin

    val text: String = getString(R.string.welcome_messages, username, mailCount)
    val styledText: Spanned = Html.fromHtml(text, FROM_HTML_MODE_LEGACY)
    

    Java

    String text = getString(R.string.welcome_messages, username, mailCount);
    Spanned styledText = Html.fromHtml(text, FROM_HTML_MODE_LEGACY);
    

Poiché il metodo fromHtml(String) formatta tutte le entità HTML, assicurati di eseguire l'escape di tutti i possibili caratteri HTML nelle stringhe che utilizzi con il testo formattato, utilizzando htmlEncode(String). Ad esempio, se formatti una stringa che contiene caratteri come "<" o "&", devi convertire questi caratteri di escape prima della formattazione. In questo modo, quando la stringa formattata viene trasmessa tramite fromHtml(String), i caratteri risultino esattamente come erano stati scritti in origine. Ecco alcuni esempi:

Kotlin

val escapedUsername: String = TextUtils.htmlEncode(username)

val text: String = getString(R.string.welcome_messages, escapedUsername, mailCount)
val styledText: Spanned = Html.fromHtml(text, FROM_HTML_MODE_LEGACY)

Java

String escapedUsername = TextUtils.htmlEncode(username);

String text = getString(R.string.welcome_messages, escapedUsername, mailCount);
Spanned styledText = Html.fromHtml(text);

Stile con elementi spannable

Un Spannable è un oggetto di testo a cui puoi applicare uno stile utilizzando le proprietà dei caratteri, come colore e spessore del carattere. Puoi usare SpannableStringBuilder per creare il testo, quindi applicare al testo gli stili definiti nel pacchetto android.text.style.

Puoi utilizzare i seguenti metodi helper per configurare gran parte del lavoro di creazione di testo estesa:

Kotlin

/**
 * Returns a CharSequence that concatenates the specified array of CharSequence
 * objects and then applies a list of zero or more tags to the entire range.
 *
 * @param content an array of character sequences to apply a style to
 * @param tags the styled span objects to apply to the content
 *        such as android.text.style.StyleSpan
 */
private fun apply(content: Array<out CharSequence>, vararg tags: Any): CharSequence {
    return SpannableStringBuilder().apply {
        openTags(tags)
        content.forEach { charSequence ->
            append(charSequence)
        }
        closeTags(tags)
    }
}

/**
 * Iterates over an array of tags and applies them to the beginning of the specified
 * Spannable object so that future text appended to the text will have the styling
 * applied to it. Do not call this method directly.
 */
private fun Spannable.openTags(tags: Array<out Any>) {
    tags.forEach { tag ->
        setSpan(tag, 0, 0, Spannable.SPAN_MARK_MARK)
    }
}

/**
 * "Closes" the specified tags on a Spannable by updating the spans to be
 * endpoint-exclusive so that future text appended to the end will not take
 * on the same styling. Do not call this method directly.
 */
private fun Spannable.closeTags(tags: Array<out Any>) {
    tags.forEach { tag ->
    if (length > 0) {
            setSpan(tag, 0, length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
        } else {
            removeSpan(tag)
        }
    }
}

Java

/**
 * Returns a CharSequence that concatenates the specified array of CharSequence
 * objects and then applies a list of zero or more tags to the entire range.
 *
 * @param content an array of character sequences to apply a style to
 * @param tags the styled span objects to apply to the content
 *        such as android.text.style.StyleSpan
 *
 */
private static CharSequence applyStyles(CharSequence[] content, Object[] tags) {
    SpannableStringBuilder text = new SpannableStringBuilder();
    openTags(text, tags);
    for (CharSequence item : content) {
        text.append(item);
    }
    closeTags(text, tags);
    return text;
}

/**
 * Iterates over an array of tags and applies them to the beginning of the specified
 * Spannable object so that future text appended to the text will have the styling
 * applied to it. Do not call this method directly.
 */
private static void openTags(Spannable text, Object[] tags) {
    for (Object tag : tags) {
        text.setSpan(tag, 0, 0, Spannable.SPAN_MARK_MARK);
    }
}

/**
 * "Closes" the specified tags on a Spannable by updating the spans to be
 * endpoint-exclusive so that future text appended to the end will not take
 * on the same styling. Do not call this method directly.
 */
private static void closeTags(Spannable text, Object[] tags) {
    int len = text.length();
    for (Object tag : tags) {
        if (len > 0) {
            text.setSpan(tag, 0, len, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        } else {
            text.removeSpan(tag);
        }
    }
}

I seguenti metodi bold, italic e color aggregano i metodi helper precedenti e mostrano esempi specifici di applicazione degli stili definiti nel pacchetto android.text.style. Puoi creare metodi simili per applicare altri tipi di stile del testo.

Kotlin

/**
 * Returns a CharSequence that applies boldface to the concatenation
 * of the specified CharSequence objects.
 */
fun bold(vararg content: CharSequence): CharSequence = apply(content, StyleSpan(Typeface.BOLD))

/**
 * Returns a CharSequence that applies italics to the concatenation
 * of the specified CharSequence objects.
 */
fun italic(vararg content: CharSequence): CharSequence = apply(content, StyleSpan(Typeface.ITALIC))

/**
 * Returns a CharSequence that applies a foreground color to the
 * concatenation of the specified CharSequence objects.
 */
fun color(color: Int, vararg content: CharSequence): CharSequence =
        apply(content, ForegroundColorSpan(color))

Java

/**
 * Returns a CharSequence that applies boldface to the concatenation
 * of the specified CharSequence objects.
 */
public static CharSequence bold(CharSequence... content) {
    return apply(content, new StyleSpan(Typeface.BOLD));
}

/**
 * Returns a CharSequence that applies italics to the concatenation
 * of the specified CharSequence objects.
 */
public static CharSequence italic(CharSequence... content) {
    return apply(content, new StyleSpan(Typeface.ITALIC));
}

/**
 * Returns a CharSequence that applies a foreground color to the
 * concatenation of the specified CharSequence objects.
 */
public static CharSequence color(int color, CharSequence... content) {
    return apply(content, new ForegroundColorSpan(color));
}

Ecco un esempio di come concatenare questi metodi per applicare vari stili alle singole parole all'interno di una frase:

Kotlin

// Create an italic "hello, " a red "world",
// and bold the entire sequence.
val text: CharSequence = bold(italic(getString(R.string.hello)),
        color(Color.RED, getString(R.string.world)))

Java

// Create an italic "hello, " a red "world",
// and bold the entire sequence.
CharSequence text = bold(italic(getString(R.string.hello)),
    color(Color.RED, getString(R.string.world)));

Il modulo core-ktx Kotlin contiene anche funzioni di estensione che rendono ancora più semplice l'utilizzo degli intervalli. Per saperne di più, puoi consultare la documentazione del pacchetto android.text su GitHub.

Per ulteriori informazioni sull'utilizzo degli intervalli, consulta i seguenti link:

Stili con annotazioni

Puoi applicare stili complessi o personalizzati utilizzando la classe Annotation insieme al tag <annotation> nei file di risorse string.xml. Il tag di annotazione consente di contrassegnare le parti della stringa per uno stile personalizzato definendo coppie chiave-valore personalizzate nel file XML che il framework converte in intervalli Annotation. Puoi quindi recuperare queste annotazioni e utilizzare la chiave e il valore per applicare lo stile.

Quando crei annotazioni, assicurati di aggiungere il tag <annotation> a tutte le traduzioni della stringa in ogni file string.xml.


Applicazione di un carattere personalizzato alla parola "testo" in tutte le lingue

Esempio: aggiunta di un carattere personalizzato

  1. Aggiungi il tag <annotation> e definisci la coppia chiave-valore. In questo caso, la chiave è font e il valore è il tipo di carattere che vogliamo utilizzare: title_emphasis.

    // values/strings.xml
    <string name="title">Best practices for <annotation font="title_emphasis">text</annotation> on Android</string>
    
    // values-es/strings.xml
    <string name="title"><annotation font="title_emphasis">Texto</annotation> en Android: mejores prácticas</string>
    
  2. Carica la risorsa stringa e trova le annotazioni con la chiave font. Quindi, crea un intervallo personalizzato e sostituisci quello esistente.

    Kotlin

    // get the text as SpannedString so we can get the spans attached to the text
    val titleText = getText(R.string.title) as SpannedString
    
    // get all the annotation spans from the text
    val annotations = titleText.getSpans(0, titleText.length, Annotation::class.java)
    
    // create a copy of the title text as a SpannableString.
    // the constructor copies both the text and the spans. so we can add and remove spans
    val spannableString = SpannableString(titleText)
    
    // iterate through all the annotation spans
    for (annotation in annotations) {
       // look for the span with the key font
       if (annotation.key == "font") {
          val fontName = annotation.value
          // check the value associated to the annotation key
          if (fontName == "title_emphasis") {
             // create the typeface
             val typeface = getFontCompat(R.font.permanent_marker)
             // set the span at the same indices as the annotation
             spannableString.setSpan(CustomTypefaceSpan(typeface),
                titleText.getSpanStart(annotation),
                titleText.getSpanEnd(annotation),
                Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
          }
       }
    }
    
    // now, the spannableString contains both the annotation spans and the CustomTypefaceSpan
    styledText.text = spannableString
    

    Java

    // get the text as SpannedString so we can get the spans attached to the text
    SpannedString titleText = (SpannedString) getText(R.string.title);
    
    // get all the annotation spans from the text
    Annotation[] annotations = titleText.getSpans(0, titleText.length(), Annotation.class);
    
    // create a copy of the title text as a SpannableString.
    // the constructor copies both the text and the spans. so we can add and remove spans
    SpannableString spannableString = new SpannableString(titleText);
    
    // iterate through all the annotation spans
    for (Annotation annotation: annotations) {
      // look for the span with the key font
      if (annotation.getKey().equals("font")) {
        String fontName = annotation.getValue();
        // check the value associated to the annotation key
        if (fontName.equals("title_emphasis")) {
        // create the typeface
        Typeface typeface = ResourcesCompat.getFont(this, R.font.roboto_mono);
        // set the span at the same indices as the annotation
        spannableString.setSpan(new CustomTypefaceSpan(typeface),
          titleText.getSpanStart(annotation),
          titleText.getSpanEnd(annotation),
          Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
      }
    }
    
    // now, the spannableString contains both the annotation spans and the CustomTypefaceSpan
    styledText.text = spannableString;
    

Se utilizzi lo stesso testo più volte, devi creare l'oggetto SpannableString una volta e riutilizzarlo come necessario per evitare potenziali problemi di prestazioni e memoria.

Per altri esempi sull'utilizzo delle annotazioni, consulta la pagina Applicare uno stile al testo internazionalizzato in Android

Intervalli di annotazione e suddivisione del testo

Poiché anche gli intervalli Annotation sono ParcelableSpans, le coppie chiave-valore vengono raggruppate e non raggruppate. Finché il destinatario dell'etichetta sa come interpretare le annotazioni, puoi utilizzare le sezioni Annotation per applicare uno stile personalizzato al testo particolato.

Per mantenere lo stile personalizzato quando passi il testo a un bundle per intent, devi prima aggiungere Annotation sezioni al testo. Puoi farlo nelle risorse XML tramite il tag <annotation>, come mostrato nell'esempio precedente, o nel codice creando un nuovo Annotation e impostandolo come intervallo, come mostrato di seguito:

Kotlin

val spannableString = SpannableString("My spantastic text")
val annotation = Annotation("font", "title_emphasis")
spannableString.setSpan(annotation, 3, 7, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)

// start Activity with text with spans
val intent = Intent(this, MainActivity::class.java)
intent.putExtra(TEXT_EXTRA, spannableString)
startActivity(intent)

Java

SpannableString spannableString = new SpannableString("My spantastic text");
Annotation annotation = new Annotation("font", "title_emphasis");
spannableString.setSpan(annotation, 3, 7, 33);

// start Activity with text with spans
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra(TEXT_EXTRA, spannableString);
this.startActivity(intent);

Recupera il testo da Bundle come SpannableString e poi analizza le annotazioni allegate, come mostrato nell'esempio precedente.

Kotlin

// read text with Spans
val intentCharSequence = intent.getCharSequenceExtra(TEXT_EXTRA) as SpannableString

Java

// read text with Spans
SpannableString intentCharSequence = (SpannableString)intent.getCharSequenceExtra(TEXT_EXTRA);

Per saperne di più sugli stili del testo, consulta i seguenti link: