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

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

это работало отлично, спасибо
Моза

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

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)любом месте приложения.


+1 простое и чистое решение. Обратите внимание на плохое написание getResourses, это getResourcesприведет к переопределению. Также шаблон синглтона кажется ненужным, возможно, его можно пропустить. Любые проблемы с утечкой памяти с этим решением?
Xarvalus

@Xarvalus это делает утечку памяти?
Хемрай

в моем приложении все нормально :) просто интересно, есть ли у кого-нибудь проблемы с этим. Я дам знать, если я столкнусь с какой-либо ловушкой.
Xarvalus

1
Утечка памяти @Xarvalus обычно происходит в том месте, где используется переменная, даже если родительский класс уничтожен. Как в деятельности, фрагменты. Я не думаю, что это произойдет в этом случае.
Хемрай


14

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

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

7

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

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

4

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

getString(android.R.string.ok)

(В этом случае строка «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 () Fragment или this of Activity.


0

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

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

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

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.