Возможно ли динамически добавить String в String.xml в Android?


495

Возможно ли иметь заполнители в строковых значениях, string.xmlкоторым можно присваивать значения во время выполнения?

Пример:

немного строки PLACEHOLDER1 еще немного строки



@HarishGyanani Нет, этот старше, что вместо этого нужно слиться с этим
Дан

Ответы:


1036

Форматирование и стиль

Да, см. Строковые ресурсы: форматирование и стилизация

Если вам нужно отформатировать строки, используя String.format(String, Object...), то вы можете сделать это, поместив аргументы формата в строковый ресурс. Например, со следующим ресурсом:

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

В этом примере строка формата имеет два аргумента: %1$sявляется строкой и %2$dявляется десятичным числом. Вы можете отформатировать строку с аргументами из вашего приложения следующим образом:

Resources res = getResources();
String text = String.format(res.getString(R.string.welcome_messages), username, mailCount);

Основное использование

Обратите внимание, что getStringесть перегрузка, которая использует строку в качестве строки формата:

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

Множественные

Если вам нужно обрабатывать множественное число, используйте это:

<plurals name="welcome_messages">
    <item quantity="one">Hello, %1$s! You have a new message.</item>
    <item quantity="other">Hello, %1$s! You have %2$d new messages.</item>
</plurals>

Первый mailCountпараметр используется, чтобы решить, какой формат использовать (одиночный или множественный), другие параметры - ваши замены:

Resources res = getResources();
String text = res.getQuantityString(R.plurals.welcome_messages, mailCount, username, mailCount);

См. Строковые ресурсы: множественное число для более подробной информации.


61
Вызов String.format в первом примере кода на самом деле не нужен, Resources.getString () поддерживает форматирование, см .: developer.android.com/reference/android/content/res/… , java.lang.Object ...)
Арно,

16
для множественного числа в String.xml необходимо указать идентификатор как R.plurals.welcome_messages вместо R.string.welcome_messages
om252345

множественное число, возвращающее только последнюю строку элемента ... любая идея, как можно получить добавление строки.
Код

1
При использовании этого метода для форматирования вашей строки он удалил все метатеги, которые вы, возможно, использовали, такие как гиперссылки и т. Д., Которые могли содержаться в тексте строки xml
Джонатан

4
Строка означает% 1 $ s, десятичная дробь -% 2 $ d, а целое - что? что означает% 1,% 2.Это подсчет параметра? .Если я хочу третий параметр Упоминание% 3?
reegan29

260

Дополнительный ответ

Когда я впервые увидел %1$sи %2$dв принятом ответе, это не имело смысла. Вот немного больше объяснений.

Они называются спецификаторами формата. В строке XML они находятся в виде

%[parameter_index$][format_type] 
  • % : Знак процента отмечает начало спецификатора формата.
  • Индекс параметра : это число, за которым следует знак доллара. Если у вас было три параметра , которые вы хотели вставить в строку, то они будут называться 1$, 2$и 3$. Порядок их размещения в строке ресурса не имеет значения, только порядок, в котором вы указываете параметры.
  • тип формата : существует множество способов форматирования ( см. документацию ). Вот некоторые из них:

    • s строка
    • d десятичное целое
    • f число с плавающей запятой

пример

Мы создадим следующую отформатированную строку, где серые части вставляются программно.

Моя сестра Maryявляется 12лет.

string.xml

<string name="my_xml_string">My sister %1$s is %2$d years old.</string>

MyActivity.java

String myString = "Mary";
int myInt = 12;
String formatted = getString(R.string.my_xml_string, myString, myInt);

Ноты

  • Я мог бы использовать, getStringпотому что я был в деятельности. Ты можешь использоватьcontext.getResources().getString(...) если он не доступен.
  • String.format() также отформатирует строку.
  • 1$И 2$условия не должны быть использованы в таком порядке. То есть 2$может прийти раньше1$ . Это полезно при интернационализации приложения для языков, которые используют другой порядок слов.
  • Вы можете использовать спецификатор формата, например, %1$sнесколько раз в xml, если хотите повторить его.
  • Используйте, %%чтобы получить реальный %характер.
  • Для получения более подробной информации прочитайте следующее полезное руководство: Android SDK Quick Tip: Форматирование строк ресурсов

125

Если вы хотите использовать параметр из фактического файла strings.xml без использования кода Java:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE resources [
  <!ENTITY appname "WhereDat">
  <!ENTITY author "Oded">
]>

<resources>
    <string name="app_name">&appname;</string>
    <string name="description">The &appname; app was created by &author;</string>
</resources>

Это не работает для файлов ресурсов, т. Е. Переменные должны быть скопированы в каждый файл XML, который нуждается в них.


Это хороший ответ, за исключением случаев, когда у вас есть параметр внутри <! [CDATA [& param; ]]>
Герман Пойлпре

2
Есть ли способ определить <!DOCTYPE... ]>деталь в отдельном файле и включить ее в несколько файлов ресурсов? Любой трюк для достижения этого?
Prom85

18

Искал то же самое и, наконец, нашел следующее очень простое решение. Лучше всего: это работает из коробки.
1. измените ваш ресурс строки:

<string name="welcome_messages">Hello, <xliff:g name="name">%s</xliff:g>! You have 
<xliff:g name="count">%d</xliff:g> new messages.</string>

2. использовать подстановку строк:

c.getString(R.string.welcome_messages,name,count);

где c - это контекст, name - строковая переменная, и подсчитайте вашу переменную int

Вам нужно будет включить

<resources xmlns:xliff="http://schemas.android.com/apk/res-auto">

в вашем res / strings.xml. Работает для меня. :)


2
Какой смысл в xliffтегах вокруг спецификаторов формата? Какую дополнительную ценность они добавляют в отличие от простого использования спецификаторов %sи %d?
Ричард Ле Мезурье

Атрибут «name» в теге xliff - это просто способ дать подсказку переводчику о том, что там будет подставлено. Иногда нелегко догадаться, что означает «% s».
Hugomg

3

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

<string name="song_number_and_title">"%1$d ~ %2$s"</string>

Создайте текстовое представление на вашем макете:

<TextView android:id="@+id/song_number_and_title"/>

Затем сделайте это в своем коде, если вы используете Anko:

val song = database.use { // get your song from the database }
song_number_and_title.setText(resources.getString(R.string.song_number_and_title, song.number, song.title))  

Возможно, вам понадобится получить ресурсы из контекста приложения.


5
Чем это отличается от примеров Java? Я не вижу разницы
Януш Хейн


1

в res / values ​​/ string.xml

<resources>
    <string name="app_name">Hello World</string>
    <string name="my_application">Application name: %s, package name: %s</string>
</resources>

в коде Java

String[] args = new String[2];
args[0] = context.getString(R.string.app_name);
args[1] = context.getPackageName();
String textMessage = context.getString(R.string.my_application,(Object[]) args);


1

Если вы хотите написать процент (%), продублируйте его:

<string name="percent">%1$d%%</string>

label.text = getString(R.string.percent, 75) // Output: 75%.

Если вы пишете просто %1$d%, вы получите сообщение об ошибке: Format string 'percent' is not a valid format string so it should not be passed to String.format.


0

Да! Вы можете сделать это без написания кода Java / Kotlin, только XML, используя эту небольшую библиотеку, которую я создал, что делает это во время сборки, поэтому ваше приложение не будет затронуто: https://github.com/LikeTheSalad/android -string ссылка

Применение

Ваши строки:

<resources>
    <string name="app_name">My App Name</string>
    <string name="template_welcome_message">Welcome to ${app_name}</string>
</resources>

Сгенерированная строка после сборки:

<!--resolved.xml-->
<resources>
    <string name="welcome_message">Welcome to My App Name</string>
</resources>

0

Прямое решение проблемы Kotlin:

strings.xml

<string name="customer_message">Hello, %1$s!\nYou have %2$d Products in your cart.</string>

kotlinActivityORFragmentFile.kt:

val username = "Andrew"
val products = 1000
val text: String = String.format(
      resources.getString(R.string.customer_message), username, products )

0

В вашем строковом файле используйте это

<string name="redeem_point"> You currently have %s points(%s points = 1 %s)</string>

И в вашем коде используйте соответственно

coinsTextTV.setText(String.format(getContext().getString(R.string.redeem_point), rewardPoints.getReward_points()
                        , rewardPoints.getConversion_rate(), getString(R.string.rs)));

-1

Котлин версия принятого ответа ...

val res = resources
val text = String.format(res.getString(R.string.welcome_messages), username, mailCount)

3
Более правильным способом является использование resources.getString(int, ... args)метода с аргументами вместо String.format. В этом коде также нет специфики kotlin, кроме valключевого слова. Смотрите ответ msbodw001
dant3
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.