Чи можна динамічно додавати String до String.xml в Android?


494

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

Приклад:

деякі рядки PLACEHOLDER1 ще деякі рядки



@HarishGyanani Ні, ця старіша, і замість цього її слід злити
Danh

Відповіді:


1034

Форматування та стилізація

Так, дивіться наступне з String Resources: Форматування та стилізація

Якщо вам потрібно відформатувати рядки за допомогою 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);

Докладнішу інформацію див. У статті String Resources: Множина .


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

16
для множини в String.xml потрібно вказати id як R.plurals.welcome_messages замість R.string.welcome_messages
om252345

множина, що повертає лише останній рядок елемента ... будь-яка ідея, як можна отримати рядок додавання.
CoDe

1
Використовуючи цей метод для форматування рядка, він видалив будь-які мета-теги, які ви, можливо, використовували, наприклад, гіперпосилання тощо, які могли б міститися в текстовому рядку XML
Джонатан

4
Рядок означає% 1 $ s, десятковий -% 2 $ d, а ціле - для чого? яке значення% 1,% 2.Чи є цей підрахунок параметра? Якщо я хочу третій параметр Згадаю% 3?
reegan29

259

Додатковий відповідь

Коли я вперше побачив %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() також буде форматувати String.
  • 1$І 2$умови не повинні бути використані в такому порядку. Тобто, 2$можна прийти і раніше 1$. Це корисно при інтернаціоналізації програми для мов, які використовують інший порядок слів.
  • Ви можете використовувати специфікатор формату, як %1$sкілька разів у xml, якщо ви хочете повторити його.
  • Використовуйте %%для отримання фактичного %персонажа.
  • Для отримання більш детальної інформації читайте наступний корисний підручник: Android SDK Швидкий підказок : Форматування рядків ресурсів

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 - контекст, ім'я - це рядкова змінна, і рахувати вашу змінну int

Вам потрібно буде включити

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

у вашому res / strings.xml. Працює для мене. :)


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

Атрибут "name" у тезі xliff - це лише спосіб дати підказку перекладачеві про те, що там буде замінено. Іноді нелегко здогадатися, що означає "% s".
hugomg

3

У Котліні потрібно просто встановити значення рядка таким чином:

<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 -подказка-посилання

Використання

Ваші рядки:

<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

Прямий вирішення проблеми Котліна:

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. У цьому коді немає специфіки котліна, крім valключового слова. Дивіться відповідь msbodw001
dant3
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.