Tempo per un aggiornamento dovuto.
Prima di tutto, l'elenco obsoleto con l'API in cui è stato deprecato:
configuration.locale
(API 17)
updateConfiguration(configuration, displaymetrics)
(API 17)
La cosa a cui non è stata data risposta a una domanda recente è l'utilizzo del nuovo metodo .
createConfigurationContext è il nuovo metodo per updateConfiguration.
Alcuni l'hanno usato da solo in questo modo:
Configuration overrideConfiguration = ctx.getResources().getConfiguration();
Locale locale = new Locale("en_US");
overrideConfiguration.setLocale(locale);
createConfigurationContext(overrideConfiguration);
... ma non funziona. Perché? Il metodo restituisce un contesto, che viene quindi utilizzato per gestire le traduzioni di Strings.xml e altre risorse localizzate (immagini, layout, qualunque cosa).
L'uso corretto è così:
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 lo hai appena copiato e incollato nel tuo IDE, potresti visualizzare un avviso che l'API richiede il targeting dell'API 17 o successiva. Questo può essere aggirato inserendolo in un metodo e aggiungendo l'annotazione@TargetApi(17)
Ma aspetta. E le API più vecchie?
È necessario creare un altro metodo utilizzando updateConfiguration senza l'annotazione 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);
Non è necessario restituire un contesto qui.
Ora, gestirli può essere difficile. In API 17+ è necessario il contesto creato (o le risorse dal contesto creato) per ottenere le risorse appropriate in base alla localizzazione. come lo gestisci?
Bene, questo è il modo in cui lo faccio:
/**
* 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;
}
Questo codice funziona con un metodo che effettua chiamate al metodo appropriato in base all'API. Questo è qualcosa che ho fatto con molte chiamate deprecate diverse (incluso Html.fromHtml). Hai un metodo che accetta gli argomenti necessari, che poi lo divide in uno dei due (o tre o più) metodi e restituisce il risultato appropriato in base al livello API. È flessibile poiché non è necessario controllare più volte, il metodo "entry" lo fa per te. Il metodo di immissione qui èsetLanguage
LEGGERE QUESTO PRIMA DI USARLO
È necessario utilizzare il contesto restituito quando si ottengono risorse. Perché? Ho visto altre risposte qui che usano createConfigurationContext e non usano il contesto che restituisce. Per farlo funzionare in questo modo, deve essere chiamato updateConfiguration. Che è deprecato. Utilizzare il contesto restituito dal metodo per ottenere risorse.
Esempio di utilizzo :
Costruttore o da qualche parte simile:
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 poi, ovunque tu voglia ottenere risorse che fai:
String fromResources = ctx.getString(R.string.helloworld);
L'uso di qualsiasi altro contesto (in teoria) romperà questo.
AFAIK devi ancora utilizzare un contesto di attività per mostrare finestre di dialogo o Brindisi. per questo puoi usare un'istanza di un'attività (se sei fuori)
E infine, utilizzare recreate()
l'attività per aggiornare il contenuto. Scorciatoia per non dover creare un intento di aggiornamento.