Android: como obtenho string de recursos usando seu nome?

553

Eu gostaria de ter 2 idiomas para a interface do usuário e separar valores de string para eles no meu arquivo 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>

Agora, preciso recuperar esses valores dinamicamente no meu aplicativo:

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

Meu problema é esse i = 0.

Por que não funciona no meu caso?

Ivan
fonte
1
Você tem certeza de que o Central.lang é um enou ru?
precisa
1
São necessárias mais informações para inspecionar seu código. qual é o estado de cada var antes de obter i? De qualquer forma, você deve usar o suporte à localização padrão no Android para simplificar as coisas.
Alin

Respostas:

1069

O link ao qual você está se referindo parece funcionar com seqüências de caracteres geradas em tempo de execução. As strings de strings.xml não são criadas em tempo de execução. Você pode obtê-los via

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

getResources()é um método da Contextclasse Se você estiver dentro de um Activityou de um Service(que estenda o contexto), poderá usá-lo como neste snippet.

Observe também que toda a dependência do idioma pode ser resolvida pela estrutura do Android . Simplesmente crie pastas diferentes para cada idioma. Se o inglês for o idioma padrão, basta inserir as strings em inglês res/values/strings.xml. Em seguida, crie uma nova pasta values-rue insira as strings russas com nomes idênticos res/values-ru/strings.xml. A partir deste ponto, o Android seleciona o correto, dependendo da localidade do dispositivo, quando você chama getString()ou faz referência a cadeias de caracteres em XML via @string/mystring. Os de res/values/strings.xmlsão os substitutos, se você não tiver uma pasta que cubra a localidade dos usuários, essa será usada como valores padrão.

Consulte Localização e fornecimento de recursos para obter mais informações.


fonte
23
Se você estiver em um android.support.v4.app.Fragment, basta ligar getString(R.string.mystring)diretamente.
JaKXz
3
Eu estava apenas vagando. Por que isso é feito (pelo google) de uma maneira tão complicada? Primeiro obtenha o ID numérico de mystring (do objeto R) e, em seguida, obtenha a string por esse ID? E onde o par "ID-de-mystring => valor real" realmente reside? Tanto quanto eu sei mystring => ID-de-mystring está em R.java, mas é isso :)
Lukáš Radek
2
certifique-se de que "R" é R do seu projeto não é o padrão android R.
ralphgabb
2
Esta pode ser a resposta que foi necessária, mas não foi a que foi solicitada! Para acessar dinamicamente um recurso de cadeia por nome, ver a resposta da @leonvian ... que deve ser o único aceite IMO
Chris Hatton
321

Eu tenho o mesmo problema. Mas este código abaixo funciona para mim: Verifique se o seu packageName está correto. Você deve consultar o pacote raiz do seu aplicativo Android.

private String getStringResourceByName(String aString) {
      String packageName = getPackageName();
      int resId = getResources().getIdentifier(aString, "string", packageName);
      return getString(resId);
    }
leonviano
fonte
9
Caso alguém tenha um bom motivo para fazer isso (por exemplo, os arquivos de dados contêm uma sequência personalizada que decide qual sequência de recursos deve ser exibida ou se essa sequência é buscada na Internet) - gostaria de salientar que esta solução é a correta. Corrija especialmente a parte em que o tipo de recurso está stringe não strings. Porque isso é lógico (como o resto do Android). Então, obrigado por isso (e mais), @leonvian. :-)
Ivan Vučica
2
@ Sameer para obter uma matriz por Strings, basta usar: res.getStringArray (R.array.planets_array); Dê uma olhada neste link oficial: developer.android.com/guide/topics/resources/…
leonvian
3
Legal. Para se livrar de uma declaração de método separado, este pode ser "simplificado" de tal modo: String someStringFromXML = getString(getResources().getIdentifier("some_string_name", "string", getPackageName()));.
Neurotransmitter
80

Não apenas das atividades:

    public static String getStringByIdName(Context context, String idName) {
        Resources res = context.getResources();
        return res.getString(res.getIdentifier(idName, "string", context.getPackageName()));
    }
konmik
fonte
funcionou muito bem obrigado
Mosa
39
getResources().getString(getResources().getIdentifier("propertyName", "string", getPackageName()))
TOUDIdel
fonte
26

Eu adicionaria algo à solução do leonvian, portanto, se por acaso a string não for encontrada entre os recursos (valor de retorno 0, que não é um código de recurso válido), a função poderá retornar 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
fonte
15

Melhor Abordagem

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

Funcionará em qualquer lugar (Utils, modelos também).

Eu li todas as respostas, todas as respostas podem fazer seu trabalho.

  • Você pode usar getString(R.string.some_string_id)em ambos Activityou Fragment.
  • Você pode usar Context.getString(R.string.some_string_id)onde você não tem acesso direto ao getString()método. Like Dialog.

Problema

Quando você não tem Contextacesso , como um método em sua Utilclasse.

Suponha abaixo o método sem contexto.

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

Agora você passará Contextcomo parâmetro neste método e usarágetString().

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

O que eu faço é

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

O que? É muito simples de usar em qualquer lugar do seu aplicativo!

Então, aqui está uma solução pela qual você pode acessar recursos de qualquer 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;
    }

}

Adicione um campo de nome à sua manifest.xml <applicationtag.

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

Agora você está pronto para ir. Use App.getAppResources().getString(R.string.some_id)em qualquer lugar do aplicativo.

Khemraj
fonte
+1 solução simples e limpa. Observe a ortografia incorreta getResourses, getResourcesisso causaria a substituição. Além disso, o padrão singleton parece desnecessário, possivelmente poderia ser ignorado. Alguma memória vaza problemas com esta solução?
Xarvalus 28/11/19
@Xarvalus Isso causa vazamento de memória?
#
no meu aplicativo tudo bem :) apenas querendo saber se alguém teve algum problema com ele. Avisarei Se encontrar alguma armadilha.
Xarvalus 28/11
1
@Xarvalus Memory Leak geralmente ocorre no local em que uma variável está sendo usada, mesmo a classe pai é destruída. Como em Atividades, Fragmentos. Eu não acho que isso ocorra neste caso.
Khemraj #
14

Uma maneira simples de obter a sequência de recursos da sequência em um TextView. Aqui resourceName é o nome do recurso

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

Se você não tiver uma referência de atividade, poderá usar seu contexto desta maneira:

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

Há também um conjunto de sequências predefinidas do Android , como "Ok", "Cancelar" e muitas outras - para que você não precise declarar tudo. Eles estão disponíveis simplesmente por:

getString(android.R.string.ok)

(Nesse caso, sequência "Ok"). Aliás, também existem outros recursos do Android disponíveis, como, por exemplo, imagens de ícones etc.

forsberg
fonte
2

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

jeito fácil

Avinash
fonte
1

Você pode tentar isso em uma atividade:

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

Em outras situações, como fragmentos, ... use

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

Para segurança, você deve adicionar: mContext.getResources (). GetString (R.string.your_string);

O mContext pode ser: contexto em onAttach () do Fragment ou no Activity.

O Thạnh Ldt
fonte
0

Se você não conseguir inseri-lo em uma atividade ou fragmnet, então:

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

Se você deseja obtê-lo de uma classe fora da atividade ou fragmento em que você não possui o contexto de atividade, use o contexto do aplicativo:

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

Use essa linha diretamente no seu arquivo java. Mantenha simples.

Owais Yosuf
fonte