Строковые ресурсы

Строковый ресурс предоставляет текстовые строки для вашего приложения с дополнительным стилем и форматированием текста. Существует три типа ресурсов, которые могут предоставить вашему приложению строки:

Нить
XML-ресурс, предоставляющий одну строку.
Строковый массив
XML-ресурс, предоставляющий массив строк.
Количественные строки (множественное число)
Ресурс XML, содержащий разные строки для множественного числа.

Ко всем строкам можно применять некоторую разметку стиля и аргументы форматирования. Информацию о стилях и форматировании строк см. в разделе « Форматирование и оформление» .

Нить

Одна строка, на которую можно ссылаться из приложения или из других файлов ресурсов (например, макета XML).

Примечание. Строка — это простой ресурс, ссылка на который осуществляется с использованием значения, указанного в атрибуте name (а не имени XML-файла). Таким образом, вы можете комбинировать строковые ресурсы с другими простыми ресурсами в одном XML-файле под одним элементом <resources> .

расположение файла:
res/values/ filename .xml
Имя файла произвольное. name элемента <string> используется в качестве идентификатора ресурса.
тип данных скомпилированного ресурса:
Указатель ресурса на String .
ссылка на ресурс:
В Java: R.string. string_name
В XML: @string/ string_name
синтаксис:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string
        name="string_name"
        >text_string</string>
</resources>
элементы:
<resources>
Необходимый. Это должен быть корневой узел.

Никаких атрибутов.

<string>
Строка, которая может включать теги стиля. Помните, что вам следует избегать апострофов и кавычек. Дополнительную информацию о том, как правильно оформлять и форматировать строки, см. в разделе «Форматирование и оформление» ниже.

атрибуты:

name
Нить . Имя для строки. Это имя используется в качестве идентификатора ресурса.
пример:
XML-файл, сохраненный в res/values/strings.xml :
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="hello">Hello!</string>
</resources>

Этот XML-макет применяет строку к представлению:

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

Этот код приложения получает строку:

Котлин

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

Ява

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

Вы можете использовать getString(int) или getText(int) для получения строки. getText(int) сохраняет любые стили форматированного текста, примененные к строке.

Строковый массив

Массив строк, на которые можно ссылаться из приложения.

Примечание. Массив строк — это простой ресурс, ссылка на который осуществляется с помощью значения, указанного в атрибуте name (а не имени XML-файла). Таким образом, вы можете комбинировать ресурсы массива строк с другими простыми ресурсами в одном XML-файле в одном элементе <resources> .

расположение файла:
res/values/ filename .xml
Имя файла произвольное. name элемента <string-array> используется в качестве идентификатора ресурса.
тип данных скомпилированного ресурса:
Указатель ресурса на массив String s.
ссылка на ресурс:
В Java: R.array. string_array_name
В 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>
Необходимый. Это должен быть корневой узел.

Никаких атрибутов.

<string-array>
Определяет массив строк. Содержит один или несколько элементов <item> .

атрибуты:

name
Нить . Имя массива. Это имя используется как идентификатор ресурса для ссылки на массив.
<item>
Строка, которая может включать теги стиля. Значение может быть ссылкой на другой строковый ресурс. Должен быть дочерним элементом элемента <string-array> . Помните, что вам следует избегать апострофов и кавычек. См. раздел «Форматирование и оформление» ниже для получения информации о правильном оформлении и форматировании строк.

Никаких атрибутов.

пример:
XML-файл, сохраненный в 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>

Этот код приложения извлекает массив строк:

Котлин

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

Ява

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

Количественные строки (множественное число)

В разных языках действуют разные правила грамматического согласования количества. В английском языке, например, количество 1 является особым случаем. Пишем «1 книга», но для любого другого количества будем писать « n книг». Это различие между единственным и множественным числом очень распространено, но в других языках существуют более тонкие различия. Полный набор, поддерживаемый Android: zero , one , two , few , many и other .

Правила принятия решения о том, какой регистр использовать для данного языка и количества, могут быть очень сложными, поэтому Android предоставляет вам такие методы, как getQuantityString() для выбора подходящего ресурса.

Хотя исторически они называются «количественными строками» (и до сих пор называются так в API), количественные строки следует использовать только для множественного числа. Было бы ошибкой использовать строки количества для реализации чего-то вроде «Входящие» Gmail вместо «Входящие (12)», например, когда есть непрочитанные сообщения. Может показаться удобным использовать количественные строки вместо оператора if , но важно отметить, что некоторые языки (например, китайский) вообще не делают этих грамматических различий, поэтому вы всегда получите other строку.

Выбор используемой строки осуществляется исключительно на основе грамматической необходимости . В английском языке строка для zero игнорируется, даже если количество равно 0, поскольку 0 грамматически не отличается от 2 или любого другого числа, кроме 1 («ноль книг», «одна книга», «две книги» и т. д.). на). И наоборот, в корейском языке всегда используется только other строка.

Не вводите в заблуждение тот факт, что, скажем, two звука, подобные этому, могут относиться только к числу 2: язык может требовать, чтобы 2, 12, 102 (и т. д.) рассматривались как друг друга, но по-разному по отношению к другим. количества. Положитесь на своего переводчика, чтобы узнать, на каких различиях на самом деле настаивает их язык.

Если ваше сообщение не содержит номера количества, вероятно, оно не является хорошим кандидатом на множественное число. Например, в литовском языке форма единственного числа используется и для 1, и для 101, поэтому «1 книга» переводится как «1 книга», а «101 книга» переводится как «101 книга». Между тем «книга» — это «кныга», а «много книг» — это «дауг книгу». Если английское сообщение во множественном числе содержит слова «книга» (единственное число) и «много книг» (множественное число) без фактического числа, его можно перевести как «knyga» (книга)/»daug knygų» (много книг), но с По литовским правилам будет отображаться «кныга» (одна книга), когда число будет 101.

Часто можно избежать строк количества, используя нейтральные по количеству формулировки, такие как «Книги: 1». Это облегчит вашу жизнь и жизнь ваших переводчиков, если такой стиль приемлем для вашего приложения.

В API 24+ вместо этого вы можете использовать гораздо более мощный класс ICU MessageFormat .

Примечание. Коллекция множественного числа — это простой ресурс, ссылка на который осуществляется с использованием значения, указанного в атрибуте name (а не имени XML-файла). Таким образом, вы можете комбинировать ресурсы множественного числа с другими простыми ресурсами в одном XML-файле под одним элементом <resources> .

расположение файла:
res/values/ filename .xml
Имя файла произвольное. name элемента <plurals> используется в качестве идентификатора ресурса.
ссылка на ресурс:
На 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>
Необходимый. Это должен быть корневой узел.

Никаких атрибутов.

<plurals>
Коллекция строк, из которых одна строка предоставляется в зависимости от количества чего-либо. Содержит один или несколько элементов <item> .

атрибуты:

name
Нить . Имя пары строк. Это имя используется в качестве идентификатора ресурса.
<item>
Строка во множественном или единственном числе. Значение может быть ссылкой на другой строковый ресурс. Должен быть дочерним элементом элемента <plurals> . Помните, что вам следует избегать апострофов и кавычек. См. раздел «Форматирование и оформление» ниже для получения информации о правильном оформлении и форматировании строк.

атрибуты:

quantity
Ключевое слово . Значение, указывающее, когда следует использовать эту строку. Допустимые значения с неисчерпывающими примерами в скобках:
Ценить Описание
zero Когда язык требует особого обращения с цифрой 0 (как в арабском языке).
one Когда язык требует особого обращения с числами, такими как единица (как с числом 1 в английском и большинстве других языков; в русском языке к этому классу относится любое число, оканчивающееся на 1, но не оканчивающееся на 11).
two Когда язык требует особого обращения с числами, такими как двойка (например, 2 в валлийском или 102 в словенском).
few Когда язык требует особого обращения с «маленькими» числами (например, 2, 3 и 4 в чешском языке; или числами, оканчивающимися на 2, 3 или 4, но не на 12, 13 или 14 в польском языке).
many Когда язык требует особого обращения с «большими» числами (например, с числами, оканчивающимися на 11–99 на мальтийском языке).
other Когда язык не требует особого обращения с данной величиной (как со всеми цифрами в китайском языке или 42 в английском языке).
пример:
XML-файл, сохраненный в 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>

XML-файл, сохраненный в 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>

Использование:

Котлин

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

Ява

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

При использовании метода getQuantityString() вам необходимо передать count дважды, если ваша строка содержит форматирование строки с числом. Например, для %d songs found первый параметр count выбирает соответствующую строку во множественном числе, а второй параметр count вставляется в заполнитель %d . Если ваши строки во множественном числе не включают форматирование строк, вам не нужно передавать третий параметр в getQuantityString .

Формат и стиль

Вот несколько важных вещей, которые вам следует знать о том, как правильно форматировать и стилизовать строковые ресурсы.

Обработка специальных символов

Если строка содержит символы, которые имеют специальное использование в XML, вы должны экранировать символы в соответствии со стандартными правилами экранирования XML/HTML. Если вам нужно экранировать символ, имеющий особое значение в Android, вам следует использовать обратную косую черту перед ним.

По умолчанию Android сжимает последовательности пробельных символов в один пробел. Вы можете избежать этого, заключив соответствующую часть строки в двойные кавычки. В этом случае все пробелы (включая новые строки) сохранятся в пределах кавычек. Двойные кавычки также позволят вам использовать обычные одинарные неэкранированные кавычки.

Характер Сбежавшие формы
@ \@
? \?
Новая линия \n
Вкладка \t
U+XXXX символ Юникода \uXXXX
Одинарная кавычка ( ' )

Любое из следующего:

  • \'
  • Заключите всю строку в двойные кавычки (например, "This'll work" ).
Двойная кавычка ( " ) \"

Обратите внимание, что заключение строки в одинарные кавычки не работает.

Свертывание пробелов и экранирование Android происходит после того, как ваш файл ресурсов анализируется как XML. Это означает, что <string> &#32; &#8200; &#8195;</string> (пробел, пробел для знаков препинания, пробел Unicode Em) все сворачиваются в один пробел ( " " ), поскольку все они являются пробелами Unicode после анализа файла как XML. Чтобы сохранить эти пробелы такими, какие они есть, вы можете либо заключить их в кавычки ( <string>" &#32; &#8200; &#8195;"</string> ), либо использовать экранирование Android ( <string> \u0032 \u8200 \u8195</string> >).

Примечание. С точки зрения анализатора XML нет никакой разницы между <string>"Test this"</string> и <string>&quot;Test this&quot;</string> . Обе формы не будут отображать кавычки, но активируют кавычки Android с сохранением пробелов (в данном случае это не будет иметь практического эффекта).

Форматирование строк

Если вам необходимо отформатировать строки, вы можете сделать это, поместив аргументы формата в строковый ресурс, как показано в следующем примере ресурса.

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

В этом примере строка формата имеет два аргумента: %1$s — это строка, а %2$d — десятичное число. Затем отформатируйте строку, вызвав getString(int, Object...) . Например:

Котлин

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

Ява

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

Стилизация с помощью HTML-разметки

Вы можете добавить стиль к своим строкам с помощью HTML-разметки. Например:

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

Поддерживаются следующие элементы HTML:

  • Жирный: <b>
  • Курсив: <i>, <cite>, <dfn>, <em>
  • Увеличение текста на 25 %: <big>
  • Текст на 20% меньше: <small>
  • Настройка свойств шрифта: <font face="font_family" color="hex_color">. Примеры возможных семейств шрифтов включают monospace , serif и sans_serif .
  • Установка семейства моноширинных шрифтов: <tt>
  • Зачеркивание: <s>, <strike>, <del>
  • Подчеркнуть: <u>
  • Надстрочный индекс: <sup>
  • Индекс: <sub>
  • Точки списка: <ul>, <li>
  • Разрывы строк: <br>
  • Подразделение: <div>
  • Стиль CSS: <span style="color|background_color|text-decoration">
  • Параграфы: <p dir="rtl | ltr» style="…">

Если вы не применяете форматирование, вы можете установить текст TextView напрямую, вызвав setText(java.lang.CharSequence) . Однако в некоторых случаях может потребоваться создать стилизованный текстовый ресурс, который также будет использоваться в качестве строки формата. Обычно это не работает, поскольку методы format(String, Object...) и getString(int, Object...) удаляют всю информацию о стиле из строки. Обходной путь заключается в написании HTML-тегов с экранированными сущностями, которые затем восстанавливаются с помощью fromHtml(String) после форматирования. Например:

  1. Сохраните свой стилизованный текстовый ресурс как строку с экранированием HTML:
    <resources>
      <string name="welcome_messages">Hello, %1$s! You have &lt;b>%2$d new messages&lt;/b>.</string>
    </resources>
    

    В эту форматированную строку добавляется элемент <b> . Обратите внимание, что открывающая скобка экранируется HTML с помощью &lt; обозначения.

  2. Затем отформатируйте строку как обычно, а также вызовите fromHtml(String) для преобразования текста HTML в стилизованный текст:

    Котлин

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

    Ява

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

Поскольку метод fromHtml(String) форматирует все объекты HTML, обязательно экранируйте любые возможные символы HTML в строках, которые вы используете с форматированным текстом, с помощью htmlEncode(String) . Например, если вы форматируете строку, содержащую такие символы, как «<» или «&», перед форматированием их необходимо экранировать, чтобы при прохождении форматированной строки через fromHtml(String) символы выходили в нужном направлении. они были написаны изначально. Например:

Котлин

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)

Ява

String escapedUsername = TextUtils.htmlEncode(username);

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

Стилизация с помощью Spanables

Spannable — это текстовый объект, который можно стилизовать с помощью свойств шрифта, таких как цвет и насыщенность шрифта. Вы используете SpannableStringBuilder для создания текста, а затем применяете к тексту стили, определенные в пакете android.text.style .

Вы можете использовать следующие вспомогательные методы для выполнения большей части работы по созданию составного текста:

Котлин

/**
 * 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)
        }
    }
}

Ява

/**
 * 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);
        }
    }
}

Следующие методы, bold , italic и color , оборачивают приведенные выше вспомогательные методы и демонстрируют конкретные примеры применения стилей, определенных в пакете android.text.style . Вы можете создать аналогичные методы для других типов стилизации текста.

Котлин

/**
 * 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))

Ява

/**
 * 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));
}

Вот пример того, как объединить эти методы вместе, чтобы применить различные стили к отдельным словам внутри фразы:

Котлин

// 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)))

Ява

// 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)));

Kotlin-модуль core-ktx также содержит функции расширения, которые еще больше упрощают работу с интервалами. Чтобы узнать больше, вы можете просмотреть документацию по пакету android.text на GitHub.

Дополнительную информацию о работе с интервалами см. по следующим ссылкам:

Стилизация с аннотациями

Вы можете применить сложный или собственный стиль, используя класс Annotation вместе с тегом <annotation> в файлах ресурсов strings.xml. Тег аннотации позволяет помечать части строки для пользовательского стиля, определяя пользовательские пары ключ-значение в XML, которые платформа затем преобразует в диапазоны Annotation . Затем вы можете получить эти аннотации и использовать ключ и значение для применения стиля.

При создании аннотаций обязательно добавляйте тег <annotation> ко всем переводам строки в каждом файле strings.xml.


Применение собственного шрифта к слову «текст» на всех языках

Пример — добавление собственного шрифта

  1. Добавьте тег <annotation> и определите пару ключ-значение. В данном случае ключом является шрифт , а значением — тип шрифта, который мы хотим использовать: 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. Загрузите строковый ресурс и найдите аннотации с помощью ключа шрифта . Затем создайте собственный диапазон и замените существующий диапазон.

    Котлин

    // 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
    

    Ява

    // 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;
    

Если вы используете один и тот же текст несколько раз, вам следует создать объект SpannableString один раз и повторно использовать его по мере необходимости, чтобы избежать потенциальных проблем с производительностью и памятью.

Дополнительные примеры использования аннотаций см. в разделе «Стилизация интернационализированного текста в Android».

Промежутки аннотаций и разделение текста

Поскольку диапазоны Annotation также являются ParcelableSpans , пары ключ-значение являются пакетированными и непакетируемыми. Если получатель посылки знает, как интерпретировать аннотации, вы можете использовать диапазоны Annotation , чтобы применить собственный стиль к фрагментированному тексту.

Чтобы сохранить собственный стиль при передаче текста в Intent Bundle, сначала необходимо добавить к тексту диапазоны Annotation . Вы можете сделать это в ресурсах XML с помощью тега <annotation>, как показано в примере выше, или в коде, создав новую Annotation и установив ее как диапазон, как показано ниже:

Котлин

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)

Ява

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);

Получите текст из Bundle как SpannableString , а затем проанализируйте прикрепленные аннотации, как показано в примере выше.

Котлин

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

Ява

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

Дополнительную информацию о стилизации текста см. по следующим ссылкам: