Android: ¿Cómo obtengo una cadena de recursos usando su nombre?

553

Me gustaría tener 2 idiomas para la interfaz de usuario y valores de cadena separados para ellos en mi archivo de recursos 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>

Ahora necesito recuperar estos valores dinámicamente en mi aplicación:

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

Mi problema es que i = 0.

¿Por qué no funciona en mi caso?

Ivan
fuente
1
¿Estás seguro de que Central.lang es eno ru?
K -ballo
1
Se necesita más información para inspeccionar su código. ¿Cuál es el estado de cada var antes de obtener i? De todos modos, debe usar el soporte de localización predeterminado en Android para simplificar las cosas.
Alin

Respuestas:

1069

El enlace al que se refiere parece funcionar con cadenas generadas en tiempo de ejecución. Las cadenas de strings.xml no se crean en tiempo de ejecución. Puedes obtenerlos a través de

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

getResources()Es un método de la Contextclase. Si está dentro de a Activityo a Service(que extienden el contexto), puede usarlo como en este fragmento.

También tenga en cuenta que el marco de Android puede ocuparse de toda la dependencia del idioma . Simplemente cree carpetas diferentes para cada idioma. Si el inglés es su idioma predeterminado, simplemente ponga las cadenas en inglés res/values/strings.xml. Luego cree una nueva carpeta values-ruy coloque las cadenas rusas con nombres idénticos res/values-ru/strings.xml. A partir de este momento, Android selecciona el correcto según la configuración regional del dispositivo, ya sea cuando llame getString()o cuando haga referencia a cadenas en XML a través de @string/mystring. Los que res/values/strings.xmlson los de respaldo, si no tiene una carpeta que cubra la configuración regional de los usuarios, esta se usará como valores predeterminados.

Consulte Localización y suministro de recursos para obtener más información.


fuente
23
Si estás en un android.support.v4.app.Fragment, puedes llamar getString(R.string.mystring)directamente.
JaKXz
3
Solo me estaba desvaneciendo. ¿Por qué se hace (por Google) de una manera tan complicada? Primero obtenga la identificación numérica de mystring (del objeto R) y luego obtenga la cadena con esa ID. ¿Y dónde reside realmente el par "ID-of-mystring => actualValue"? Hasta donde sé mystring => ID-of-mystring está en R.java, pero eso es todo :)
Lukáš Řádek
2
asegúrese de que "R" es R de su proyecto no es el predeterminado androide R.
ralphgabb
2
Esta puede ser la respuesta que se necesitaba, ¡pero no fue la que se solicitó! Para acceder dinámicamente a un recurso de cadena por nombre, vea la respuesta de @leonvian ... que debería ser la IMO aceptada
Chris Hatton
321

Tengo el mismo problema. Pero este código a continuación funciona para mí: Verifique si su packageName es correcto. Debe consultar el paquete raíz de su aplicación de Android.

private String getStringResourceByName(String aString) {
      String packageName = getPackageName();
      int resId = getResources().getIdentifier(aString, "string", packageName);
      return getString(resId);
    }
leonvian
fuente
99
En caso de que alguien tenga una buena razón para hacer esto (por ejemplo, los archivos de datos contienen una cadena personalizada que decide qué cadena de recursos se debe mostrar, o si esta cadena se obtiene de Internet), entonces me gustaría señalar que Esta solución es la correcta. Especialmente corrija la parte donde el tipo de recurso es stringy no strings. Porque eso es lógico (como el resto de Android). Entonces, gracias por eso (y más), @leonvian. :-)
Ivan Vučica
2
@Sameer para obtener una matriz de Strings solo use: res.getStringArray (R.array.planets_array); Eche un vistazo a este enlace oficial: developer.android.com/guide/topics/resources/…
leonvian
3
Frio. Para deshacerse de una declaración de método separado, esto puede ser "simplificado" de tal manera: String someStringFromXML = getString(getResources().getIdentifier("some_string_name", "string", getPackageName()));.
Neurotransmisor
80

No solo de actividades:

    public static String getStringByIdName(Context context, String idName) {
        Resources res = context.getResources();
        return res.getString(res.getIdentifier(idName, "string", context.getPackageName()));
    }
konmik
fuente
funcionó muy bien gracias
Mosa
39
getResources().getString(getResources().getIdentifier("propertyName", "string", getPackageName()))
TOUDIdel
fuente
26

Agregaría algo a la solución de leonvian, por lo que si por casualidad la cadena no se encuentra entre los recursos (valor de retorno 0, ese no es un código de recurso válido), la función podría devolver algo:

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

Mejor enfoque

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

Funcionará en todas partes (utilidades, modelos también).

He leído todas las respuestas, todas las respuestas pueden hacer tu trabajo.

  • Se puede usar getString(R.string.some_string_id)en ambos Activityo Fragment.
  • Puede usar Context.getString(R.string.some_string_id)donde no tiene acceso directo al getString()método. Al igual Dialog.

Problema

Cuando no tienes Contextacceso , como un método en tu Utilclase.

Asuma el siguiente método sin contexto.

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

Ahora pasará Contextcomo parámetro en este método y usarágetString().

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

Lo que hago es

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

¿Qué? ¡Es muy fácil de usar en cualquier lugar de su aplicación!

Así que aquí hay una solución mediante la cual puede acceder a los recursos desde cualquier lugar 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;
    }

}

Agregue un campo de nombre a su manifest.xml <applicationetiqueta.

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

Ahora estás listo para irte. Usar App.getAppResources().getString(R.string.some_id)en cualquier lugar de la aplicación.

Khemraj
fuente
+1 solución simple y limpia. Observe que la ortografía es incorrecta getResourses, getResourcescausaría una anulación. Además, el patrón singleton parece innecesario, posiblemente podría omitirse. ¿Alguna pérdida de memoria tiene problemas con esta solución?
Xarvalus
@Xarvalus ¿Esto hace que se pierda memoria?
Khemraj
en mi aplicación todo bien :) solo me preguntaba si alguien tenía algún problema con eso. Lo haré saber si encuentro algún obstáculo.
Xarvalus
1
La pérdida de memoria de @Xarvalus generalmente ocurre en el lugar donde se usa una variable, incluso la clase principal se destruye. Como en Actividades, Fragmentos. No creo que ocurra en este caso.
Khemraj
14

Una forma sencilla de obtener una cadena de recursos de una cadena en un TextView. Aquí resourceName es el nombre del recurso

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

Si no tiene una referencia de Actividad, puede usar su contexto de esta manera:

getContext().getString(R.string.your_string_name);
Hazlo8
fuente
4

También hay un conjunto de cadenas de Android predefinidas como "Ok", "Cancelar" y muchas otras, por lo que no tiene que declararlas todas. Están disponibles simplemente por:

getString(android.R.string.ok)

(En este caso, cadena "Ok"). Por cierto, también hay otros recursos de Android disponibles como, por ejemplo, imágenes de iconos, etc.

forsberg
fuente
2

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

camino fácil

Avinash
fuente
1

Puedes probar esto en una Actividad:

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

En otras situaciones como fragmentos, ... use

getContext().getResources().getString(R.string.your string name);
M Shafaei N
fuente
0

Para proteger, debe agregar: mContext.getResources (). GetString (R.string.your_string);

mContext puede ser: contexto en onAttach () de Fragment o this of Activity.

O Thạnh Ldt
fuente
0

Si desea obtenerlo dentro de una actividad o fragmnet, entonces:

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

Si desea obtenerlo de una clase fuera de la actividad o fragmento donde no tiene el contexto de la actividad, use el contexto de la aplicación:

getApplicationContext().getResources().getString(R.string.string_name);
rohegde7
fuente
0
R.string.<string_name>

Use esa línea directamente en su archivo java. Mantenlo simple.

Owais Yosuf
fuente