Zeit für ein fälliges Update.
Zunächst die veraltete Liste mit der API, in der sie veraltet war:
configuration.locale
(API 17)
updateConfiguration(configuration, displaymetrics)
(API 17)
Das, was in letzter Zeit nicht richtig beantwortet wurde, ist die Verwendung der neuen Methode .
createConfigurationContext ist die neue Methode für updateConfiguration.
Einige haben es eigenständig wie folgt verwendet:
Configuration overrideConfiguration = ctx.getResources().getConfiguration();
Locale locale = new Locale("en_US");
overrideConfiguration.setLocale(locale);
createConfigurationContext(overrideConfiguration);
... aber das geht nicht. Warum? Die Methode gibt einen Kontext zurück, der dann zur Verarbeitung von Strings.xml-Übersetzungen und anderen lokalisierten Ressourcen (Bilder, Layouts usw.) verwendet wird.
Die richtige Verwendung ist wie folgt:
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();
Wenn Sie dies gerade in Ihre IDE kopiert haben, wird möglicherweise eine Warnung angezeigt, dass die API erfordert, dass Sie auf API 17 oder höher abzielen. Dies kann umgangen werden, indem Sie es in eine Methode einfügen und die Anmerkung hinzufügen@TargetApi(17)
Aber warte. Was ist mit den älteren APIs?
Sie müssen eine andere Methode mit updateConfiguration ohne die TargetApi-Annotation erstellen.
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);
Sie müssen hier keinen Kontext zurückgeben.
Jetzt kann es schwierig sein, diese zu verwalten. In API 17+ benötigen Sie den erstellten Kontext (oder die Ressourcen aus dem erstellten Kontext), um die entsprechenden Ressourcen basierend auf der Lokalisierung zu erhalten. Wie gehst du damit um?
Nun, so mache ich das:
/**
* 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;
}
Dieser Code verfügt über eine Methode, die basierend auf welcher API die entsprechende Methode aufruft. Dies ist etwas, was ich mit vielen verschiedenen veralteten Aufrufen gemacht habe (einschließlich Html.fromHtml). Sie haben eine Methode, die die erforderlichen Argumente aufnimmt, die sie dann in eine von zwei (oder drei oder mehr) Methoden aufteilt und das entsprechende Ergebnis basierend auf der API-Ebene zurückgibt. Es ist flexibel, da Sie nicht mehrmals prüfen müssen. Die "Eingabemethode" erledigt dies für Sie. Die Eingabemethode hier istsetLanguage
BITTE LESEN SIE DIESES, BEVOR SIE ES VERWENDEN
Sie müssen den zurückgegebenen Kontext verwenden, wenn Sie Ressourcen erhalten. Warum? Ich habe hier andere Antworten gesehen, die createConfigurationContext verwenden und den zurückgegebenen Kontext nicht verwenden. Damit es so funktioniert, muss updateConfiguration aufgerufen werden. Welches ist veraltet. Verwenden Sie den von der Methode zurückgegebenen Kontext, um Ressourcen abzurufen.
Anwendungsbeispiel :
Konstruktor oder ähnliches:
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)
Und wo immer Sie Ressourcen erhalten möchten, tun Sie Folgendes:
String fromResources = ctx.getString(R.string.helloworld);
Die Verwendung eines anderen Kontexts wird dies (theoretisch) aufheben.
AFAIK Sie müssen immer noch einen Aktivitätskontext verwenden, um Dialoge oder Toasts anzuzeigen. Dafür können Sie eine Instanz einer Aktivität verwenden (wenn Sie sich außerhalb befinden).
Verwenden Sie schließlich recreate()
die Aktivität, um den Inhalt zu aktualisieren. Verknüpfung, um keine Aktualisierungsabsicht erstellen zu müssen.