Android: Як отримати рядок з ресурсів, використовуючи його ім’я?


553

Я хотів би, щоб у моєму файлі ресурсів було 2 мови для інтерфейсу користувача та окремі значення рядків для них res\values\strings.xml:

<string name="tab_Books_en">Books</string>
<string name="tab_Quotes_en">Quotes</string>
<string name="tab_Questions_en">Questions</string>
<string name="tab_Notes_en">Notes</string>
<string name="tab_Bookmarks_en">Bookmarks</string>

<string name="tab_Books_ru">Книги</string>
<string name="tab_Quotes_ru">Цитаты</string>
<string name="tab_Questions_ru">Вопросы</string>
<string name="tab_Notes_ru">Заметки</string>
<string name="tab_Bookmarks_ru">Закладки</string>

Тепер мені потрібно динамічно отримати ці значення:

spec.setContent(R.id.tabPage1);
String pack = getPackageName();
String id = "tab_Books_" + Central.lang;
int i = Central.Res.getIdentifier(id, "string", pack);
String str = Central.Res.getString(i);

Моя проблема в тому i = 0.

Чому це не працює в моєму випадку?


1
Ви впевнені, що Central.lang є enабо ru?
K-бал

1
Більше інформації потрібно для перевірки вашого коду. який стан кожного var перед отриманням i? У будь-якому випадку, ви повинні використовувати підтримку локалізації за замовчуванням в Android, щоб все було просто.
Алін

Відповіді:


1069

Посилання, на яке ви посилаєтесь, здається, працює з рядками, створеними під час виконання. Строки з strings.xml не створюються під час виконання. Ви можете отримати їх через

String mystring = getResources().getString(R.string.mystring);

getResources()- метод Contextкласу. Якщо ви перебуваєте всередині a Activityчи aService (що розширює контекст), ви можете використовувати його, як у цьому фрагменті.

Також зауважте, що вся мовна залежність може бути забезпечена андроїдними рамками . Просто створіть різні папки для кожної мови. Якщо англійською мовою є ваша мова за замовчуванням, просто вставте англійські рядки res/values/strings.xml. Потім створіть нову папку values-ruі вставте в неї російські рядки з однаковими іменами res/values-ru/strings.xml. З цього моменту андроїд вибирає правильний, залежно від місцеположення пристрою для вас, або під час дзвінка, getString()або під час посилання рядків у XML через @string/mystring. Одні з них res/values/strings.xmlє резервними, якщо у вас немає папки, що охоплює локальний список користувачів, ця буде використовуватися як значення за замовчуванням.

Додаткову інформацію див. У розділі Локалізація та надання ресурсів .


23
Якщо ви перебуваєте в службі android.support.v4.app.Fragment, ви можете просто зателефонувати getString(R.string.mystring)безпосередньо.
JaKXz

3
Я просто волочився. Чому це робиться (google) настільки складний спосіб? Спочатку отримайте числовий ідентифікатор містеріни (від об’єкта R), а потім отримайте рядок за цим ідентифікатором? А де пара "ID-of-mystring => currentValue" насправді перебуває? Наскільки я знаю, mystring => Ідентифікатор-mystring є у R.java, але це все :)
Lukáš Řádek

2
переконайтеся, що "R" - це R вашого проекту, а не за замовчуванням android R.
ralphgabb

2
Це може бути відповідь, яка була потрібна, але це було не те, про що просили! Для динамічного доступу до рядкового ресурсу по імені дивіться відповідь від @leonvian ... яка повинна бути прийнятою IMO
Кріс Хаттон

321

У мене така ж проблема. Але цей код нижче працює для мене: Перевірте, чи правильно вказано ваше ім'я пакета. Потрібно звернутися до кореневого пакету програми Android.

private String getStringResourceByName(String aString) {
      String packageName = getPackageName();
      int resId = getResources().getIdentifier(aString, "string", packageName);
      return getString(resId);
    }

9
Якщо у когось є вагомі причини для цього (наприклад, файли даних містять власну рядок, який вирішує, який рядок ресурсу потрібно відображати, або якщо цей рядок виведений з Інтернету) - тоді я хотів би зазначити, що це рішення є правильним. Особливо виправте ту частину, де знаходиться тип ресурсу, stringа ні strings. Тому що це логічно (як і решта Android). Тож, дякую за це (і більше) @leonvian. :-)
Іван Вучиця

2
@Sameer, щоб отримати масив Strings, просто використовуйте: res.getStringArray (R.array.planets_array); Подивіться на це офіційне посилання: developer.android.com/guide/topics/resources/…
leonvian

3
Класно. Для того, щоб позбутися від окремого оголошення методи, це може бути «спростило» таким чином: String someStringFromXML = getString(getResources().getIdentifier("some_string_name", "string", getPackageName()));.
Нейромедіатор

80

Не тільки від діяльності:

    public static String getStringByIdName(Context context, String idName) {
        Resources res = context.getResources();
        return res.getString(res.getIdentifier(idName, "string", context.getPackageName()));
    }

це спрацювало велике спасибі
Моза

39
getResources().getString(getResources().getIdentifier("propertyName", "string", getPackageName()))

26

Я додав би щось до леонвіанського рішення, тож якщо випадково рядок не знайдеться серед ресурсів (повернене значення 0, тобто не дійсний код ресурсу), функція може щось повернути:

private String getStringResourceByName(String aString) {
    String packageName = getPackageName();
    int resId = getResources()
            .getIdentifier(aString, "string", packageName);
    if (resId == 0) {
        return aString;
    } else {
        return getString(resId);
    }
}

15

Кращий підхід

App.getRes().getString(R.string.some_id)

Буде працювати скрізь (Утиліти, Моделі також).

Я прочитав усі відповіді, всі відповіді можуть зробити вашу роботу.

  • Ви можете використовувати getString(R.string.some_string_id)в обох Activityабо Fragment.
  • Ви можете використовувати Context.getString(R.string.some_string_id)там, де у вас немає прямого доступу до getString()методу. Як Dialog.

Проблема

Коли у вас немає Contextдоступу , як метод у вашому Utilкласі.

Припустимо нижче метод без контексту.

public void someMethod(){
    ...
    // can't use getResource() or getString() without Context.
}

Тепер ви перейдете Contextяк параметр у цьому методі та використаєтеgetString().

public void someMethod(Context context){
    ...
    context.getString(R.string.some_id);
}

Що я роблю, так і є

public void someMethod(){
    ...
    App.getAppResources().getString(R.string.some_id)
}

Що? Це дуже просто використовувати в будь-якому місці вашого додатка!

Тож ось рішення, за допомогою якого ви можете отримати доступ до ресурсів з будь-якого місця Util class.

import android.app.Application;
import android.content.res.Resources;

public class App extends Application {
    private static Resources resources;

    @Override
    public void onCreate() {
        super.onCreate();

        resources = getResources();
    }

    public static Resources getAppResources() {
        return resources;
    }

}

Додайте поле до імені до свого manifest.xml <applicationтегу.

<application
        android:name=".App"
        ...
        >
        ...
    </application>

Тепер вам добре піти. Використовуйте App.getAppResources().getString(R.string.some_id)будь-де в додатку.


+1 просте та чисте рішення. Помітьте неправильне написання getResourses, це getResourcesможе викликати переоцінку. Також однотонний візерунок здається непотрібним, можливо, його можна пропустити. Будь-яка пам'ять протікає з цим рішенням?
Xarvalus

@Xarvalus Це робить витік пам'яті?
Хемрайдж

в моєму додатку все добре :) просто цікаво, чи хтось із цим мав якісь проблеми. Я повідомляю, якщо я зіткнуся з будь-якою падінням.
Xarvalus

1
@Xarvalus Витік пам'яті зазвичай виникає там, де використовується змінна, навіть батьківський клас знищений. Як і в діяльності, фрагменти. Я не думаю, що це відбудеться в цьому випадку.
Хемрайдж


14

Простий спосіб отримати рядок ресурсу з рядка в TextView. Тут resourceName - назва ресурсу

int resID = getResources().getIdentifier(resourceName, "string", getPackageName());
textview.setText(resID);

7

Якщо у вас немає посилання на активність, ви можете використовувати свій контекст таким чином:

getContext().getString(R.string.your_string_name);

4

Існує також набір попередньо визначених рядків Android, таких як "Добре", "Скасувати" та багато інших - тому вам не потрібно декларувати всіх. Вони доступні просто:

getString(android.R.string.ok)

(У цьому випадку рядок "Добре"). До речі, доступні й інші ресурси Android, наприклад, зображення зображень тощо.



1

Ви можете спробувати це в рамках діяльності:

getResources().getString(R.string.your string name);

В інших ситуаціях, таких як фрагменти, ... використання

getContext().getResources().getString(R.string.your string name);

0

Для безпечності слід додати: mContext.getResources (). GetString (R.string.your_string);

mContext може бути: контекстом у onAttach () фрагмента або цього Activity.


0

Якщо ви хочете отримати його всередині діяльності або фрагмент-мережі, тоді:

getContext().getResources().getString(R.string.string_name);

Якщо ви хочете отримати його з класу поза діяльністю або фрагмента, де у вас немає контексту діяльності, тоді використовуйте контекст програми:

getApplicationContext().getResources().getString(R.string.string_name);

0
R.string.<string_name>

Використовуйте цей рядок прямо у вашому файлі Java. Не ускладнювати.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.