Hora de uma atualização devida.
Primeiro, a lista preterida com a API na qual foi preterida:
configuration.locale
(API 17)
updateConfiguration(configuration, displaymetrics)
(API 17)
A coisa que nenhuma pergunta respondida recentemente acertou é o uso do novo método .
createConfigurationContext é o novo método para updateConfiguration.
Alguns o usaram autônomo assim:
Configuration overrideConfiguration = ctx.getResources().getConfiguration();
Locale locale = new Locale("en_US");
overrideConfiguration.setLocale(locale);
createConfigurationContext(overrideConfiguration);
... mas isso não funciona. Por quê? O método retorna um contexto, que é usado para manipular traduções Strings.xml e outros recursos localizados (imagens, layouts, qualquer que seja).
O uso adequado é assim:
Configuration overrideConfiguration = ctx.getResources().getConfiguration();
Locale locale = new Locale("en_US");
overrideConfiguration.setLocale(locale);
//the configuration can be used for other stuff as well
Context context = createConfigurationContext(overrideConfiguration);
Resources resources = context.getResources();
Se você acabou de copiar e colar isso no seu IDE, poderá receber um aviso de que a API exige que você direcione a API 17 ou superior. Isso pode ser contornado, colocando-o em um método e adicionando a anotação@TargetApi(17)
Mas espere. E as APIs mais antigas?
Você precisa criar outro método usando updateConfiguration sem a anotação TargetApi.
Resources res = YourApplication.getInstance().getResources();
// Change locale settings in the app.
DisplayMetrics dm = res.getDisplayMetrics();
android.content.res.Configuration conf = res.getConfiguration();
conf.locale = new Locale("th");
res.updateConfiguration(conf, dm);
Você não precisa retornar um contexto aqui.
Agora, gerenciar isso pode ser difícil. Na API 17+, você precisa do contexto criado (ou dos recursos do contexto criado) para obter os recursos apropriados com base na localização. Como você lida com isso?
Bem, é assim que eu faço:
/**
* Full locale list: /programming/7973023/what-is-the-list-of-supported-languages-locales-on-android
* @param lang language code (e.g. en_US)
* @return the context
* PLEASE READ: This method can be changed for usage outside an Activity. Simply add a COntext to the arguments
*/
public Context setLanguage(String lang/*, Context c*/){
Context c = AndroidLauncher.this;//remove if the context argument is passed. This is a utility line, can be removed totally by replacing calls to c with the activity (if argument Context isn't passed)
int API = Build.VERSION.SDK_INT;
if(API >= 17){
return setLanguage17(lang, c);
}else{
return setLanguageLegacy(lang, c);
}
}
/**
* Set language for API 17
* @param lang
* @param c
* @return
*/
@TargetApi(17)
public Context setLanguage17(String lang, Context c){
Configuration overrideConfiguration = c.getResources().getConfiguration();
Locale locale = new Locale(lang);
Locale.setDefault(locale);
overrideConfiguration.setLocale(locale);
//the configuration can be used for other stuff as well
Context context = createConfigurationContext(overrideConfiguration);//"local variable is redundant" if the below line is uncommented, it is needed
//Resources resources = context.getResources();//If you want to pass the resources instead of a Context, uncomment this line and put it somewhere useful
return context;
}
public Context setLanguageLegacy(String lang, Context c){
Resources res = c.getResources();
// Change locale settings in the app.
DisplayMetrics dm = res.getDisplayMetrics();//Utility line
android.content.res.Configuration conf = res.getConfiguration();
conf.locale = new Locale(lang);//setLocale requires API 17+ - just like createConfigurationContext
Locale.setDefault(conf.locale);
res.updateConfiguration(conf, dm);
//Using this method you don't need to modify the Context itself. Setting it at the start of the app is enough. As you
//target both API's though, you want to return the context as you have no clue what is called. Now you can use the Context
//supplied for both things
return c;
}
Esse código funciona com um método que faz chamadas para o método apropriado com base em qual API. Isso é algo que fiz com muitas chamadas obsoletas diferentes (incluindo Html.fromHtml). Você tem um método que aceita os argumentos necessários, que o divide em um dos dois (ou três ou mais) métodos e retorna o resultado apropriado com base no nível da API. É flexível, pois você não precisa verificar várias vezes, o método "entry" faz isso por você. O método de entrada aqui ésetLanguage
LEIA ISTO ANTES DE USAR
Você precisa usar o contexto retornado ao obter recursos. Por quê? Vi outras respostas aqui que usam createConfigurationContext e não usam o contexto que ele retorna. Para que funcione dessa maneira, é necessário chamar updateConfiguration. Qual foi preterido. Use o contexto retornado pelo método para obter recursos.
Exemplo de uso :
Construtor ou em algum lugar semelhante:
ctx = getLanguage(lang);//lang is loaded or generated. How you get the String lang is not something this answer handles (nor will handle in the future)
E então, onde você quiser obter os recursos que você faz:
String fromResources = ctx.getString(R.string.helloworld);
Usar qualquer outro contexto (em teoria) irá quebrar isso.
AFAIK, você ainda precisa usar um contexto de atividade para mostrar diálogos ou brindes. para isso, você pode usar uma instância de uma atividade (se estiver fora)
E, finalmente, use recreate()
a atividade para atualizar o conteúdo. Atalho para não precisar criar uma intenção de atualização.