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?
К-балл
1
Для проверки вашего кода необходима дополнительная информация. в каком состоянии каждая переменная перед тем, как получить i? В любом случае, вы должны использовать поддержку локализации по умолчанию в Android, чтобы все было просто.
Алин

Ответы:

1069

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

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

getResources()это метод Contextкласса. Если вы находитесь внутри a Activityили a Service(что расширяет контекст), вы можете использовать его как в этом фрагменте.

Также обратите внимание, что вся языковая зависимость может быть решена с помощью платформы Android . Просто создайте разные папки для каждого языка. Если английский является вашим языком по умолчанию, просто поместите английские строки в res/values/strings.xml. Затем создайте новую папку values-ruи поместите русские строки с одинаковыми именами в res/values-ru/strings.xml. С этого момента Android выбирает правильный в зависимости от локали устройства для вас, когда вы звоните getString()или когда ссылаетесь на строки в XML через @string/mystring. Те из них res/values/strings.xmlявляются запасными, если у вас нет папки, охватывающей язык пользователя, эта будет использоваться в качестве значений по умолчанию.

См. Локализация и предоставление ресурсов для получения дополнительной информации.


источник
23
Если вы находитесь в android.support.v4.app.Fragment, вы можете просто позвонить getString(R.string.mystring)напрямую.
JaKXz
3
Я просто болтался. Почему это сделано (Google) таким сложным способом? Сначала получить числовой идентификатор mystring (из объекта R), а затем получить строку по этому идентификатору? И где на самом деле находится пара "ID-of-mystring => actualValue"? Насколько я знаю, mystring => ID-of-mystring находится в R.java, но это так :)
Lukáš Řádek
2
убедитесь, что «R» - это R вашего проекта, а не Android по умолчанию R.
ralphgabb
2
Это может быть ответом, который был необходим, но это был не тот вопрос, который просили! Для динамического доступа к строковому ресурсу по имени см. Ответ от @leonvian ... который должен быть принят IMO
Крис Хаттон
321

У меня такая же проблема. Но этот код ниже работает для меня: Проверьте правильность вашего packageName. Вы должны обратиться к корневому пакету вашего приложения Android.

private String getStringResourceByName(String aString) {
      String packageName = getPackageName();
      int resId = getResources().getIdentifier(aString, "string", packageName);
      return getString(resId);
    }
leonvian
источник
9
Если у кого-то есть веская причина для этого (например, файлы данных содержат пользовательскую строку, которая решает, какая строка ресурса должна быть отображена, или если эта строка извлекается из Интернета), - тогда я хотел бы указать, что это решение является правильным. Особенно исправьте ту часть, где тип ресурса есть stringи нет strings. Потому что это логично (как и в остальной части Android). Итак, спасибо за это (и больше), @leonvian. :-)
Иван Вучица,
2
@Sameer для получения массива по строкам просто используйте: 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()));
    }
konmik
источник
это работало отлично, спасибо
Моза
39
getResources().getString(getResources().getIdentifier("propertyName", "string", getPackageName()))
TOUDIdel
источник
26

Я бы добавил что-то к решению leonvian, так что, если по какой-либо причине строка не найдена среди ресурсов (возвращаемое значение 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)

Будет работать везде (Utils, Models также).

Я прочитал все ответы, все ответы могут сделать вашу работу.

  • Вы можете использовать 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)любом месте приложения.

Khemraj
источник
+1 простое и чистое решение. Обратите внимание на плохое написание getResourses, это getResourcesприведет к переопределению. Также шаблон синглтона кажется ненужным, возможно, его можно пропустить. Любые проблемы с утечкой памяти с этим решением?
Xarvalus
@Xarvalus это делает утечку памяти?
Хемрай
в моем приложении все нормально :) просто интересно, есть ли у кого-нибудь проблемы с этим. Я дам знать, если я столкнусь с какой-либо ловушкой.
Xarvalus
1
Утечка памяти @Xarvalus обычно происходит в том месте, где используется переменная, даже если родительский класс уничтожен. Как в деятельности, фрагменты. Я не думаю, что это произойдет в этом случае.
Хемрай
14

Проще всего использовать эту getString()функцию в упражнении.

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

Ссылка: http://developer.android.com/guide/topics/resources/string-resource.html

Я думаю, что эта функция добавлена ​​в последней версии Android, любой, кто знает историю, может прокомментировать это.

Эрен Йилмаз
источник
14

Простой способ получить строку ресурса из строки в TextView. Здесь resourceName - это имя ресурса.

int resID = getResources().getIdentifier(resourceName, "string", getPackageName());
textview.setText(resID);
Мухаммед Адиль
источник
7

Если у вас нет ссылки на Activity, вы можете использовать свой контекст следующим образом:

getContext().getString(R.string.your_string_name);
Hazlo8
источник
4

Существует также набор предопределенных строк Android, таких как «Ok», «Cancel» и многие другие - так что вам не нужно объявлять все. Они доступны просто:

getString(android.R.string.ok)

(В этом случае строка «Ok»). Кстати, есть и другие ресурсы Android, такие как, например, изображения значков и т. Д.

Форсберг
источник
2

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

Простой способ

Авинаш
источник
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 () Fragment или this of Activity.

O Thạnh Ldt
источник
0

Если вы хотите получить его внутри действия или фрагмента, то:

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

Если вы хотите получить его из класса вне действия или фрагмента, где у вас нет контекста действия, используйте контекст приложения:

getApplicationContext().getResources().getString(R.string.string_name);
rohegde7
источник
0
R.string.<string_name>

Используйте эту строку прямо в вашем Java-файле. Будь проще.

Оваис Йосуф
источник