Zeit für ein fälliges Update.
Zunächst einmal die Liste der veralteten Produkte mit der API, in der sie veraltet sind:
configuration.locale
(API 17)
updateConfiguration(configuration, displaymetrics)
(API 17)
Was in keiner der kürzlich beantworteten Fragen richtig beantwortet wurde, ist die Anwendung der neuen Methode .
createConfigurationContext ist die neue Methode für updateConfiguration.
Einige haben es als eigenständiges Produkt verwendet:
Configuration overrideConfiguration = ctx.getResources().getConfiguration();
Locale locale = new Locale("en_US");
overrideConfiguration.setLocale(locale);
createConfigurationContext(overrideConfiguration);
... aber das funktioniert nicht. Und warum? Die Methode gibt einen Kontext zurück, der dann verwendet wird, um Strings.xml-Übersetzungen und andere lokalisierte Ressourcen (Bilder, Layouts, was auch immer) zu behandeln.
Die korrekte 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 das einfach in Ihre IDE kopieren, sehen Sie möglicherweise eine Warnung, dass die API API 17 oder höher erfordert. Dies kann umgangen werden, indem man es in eine Methode einfügt und die Anmerkung hinzufügt @TargetApi(17)
Aber halt. 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.
Diese zu verwalten, kann schwierig sein. In API 17+ benötigen Sie den erstellten Kontext (oder die Ressourcen aus dem erstellten Kontext), um die entsprechenden Ressourcen auf der Grundlage der Lokalisierung zu erhalten. Wie handhaben Sie das?
Nun, ich mache es folgendermaßen:
/**
* Full locale list: https://stackoverflow.com/questions/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 funktioniert mit einer Methode, die je nach API die entsprechende Methode aufruft. Dies ist etwas, das ich mit vielen verschiedenen veralteten Aufrufen gemacht habe (einschließlich Html.fromHtml). Sie haben eine Methode, die die benötigten Argumente aufnimmt, die dann in eine von zwei (oder drei oder mehr) Methoden aufgeteilt wird und das entsprechende Ergebnis auf der Grundlage der API-Ebene zurückgibt. Es ist flexibel, da Sie nicht mehrfach prüfen müssen, sondern die "entry"-Methode dies für Sie erledigt. Die "entry"-Methode ist hier setLanguage
BITTE LESEN SIE DIES, BEVOR SIE ES BENUTZEN
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 nutzen. Damit es so funktioniert, muss updateConfiguration aufgerufen werden. Das ist veraltet. Verwenden Sie den von der Methode zurückgegebenen Kontext, um Ressourcen zu erhalten.
Beispiel für die Verwendung :
Constructor oder etwas Ä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 dann, wo immer Sie Ressourcen erhalten wollen, tun Sie es:
String fromResources = ctx.getString(R.string.helloworld);
Die Verwendung eines anderen Kontextes würde dies (theoretisch) zunichte machen.
AFAIK müssen Sie immer noch einen Aktivitätskontext verwenden, um Dialoge oder Toasts anzuzeigen. dafür können Sie eine Instanz einer Aktivität verwenden (wenn Sie außerhalb sind)
Und schließlich, verwenden Sie recreate()
auf die Aktivität, um den Inhalt zu aktualisieren. Abkürzung, um keine Absicht zur Aktualisierung erstellen zu müssen.