问题
I'm trying to change the language of the application according to the user's input. I tried using this code to change the language of the application and it's working pretty fine.
public void setLocale(String lang) {
myLocale = new Locale(lang);
Resources res = getResources();
DisplayMetrics dm = res.getDisplayMetrics();
Configuration conf = res.getConfiguration();
conf.locale = myLocale;
res.updateConfiguration(conf, dm);
Intent refresh = new Intent(MainActivity.this, MainActivity.class);
startActivity(refresh);
}
But the problem is that app has to restart/refresh in order to reload the resources.
- Is this the correct approach to set the language of the app programmatically?
- Is there any other way to change the language without refreshing the app?
回答1:
Try with recreate() on your activity. This approach was successful in my case. If you are on Fragment, then use getActivity().recreate();
SharedPreferences.Editor editor = prefs.edit();
editor.putString(Constants.APP_STATE.SAVED_LOCALE, localeString);
editor.apply();
getActivity().recreate();
Override following method of your activity:
@Override
protected void attachBaseContext(Context newBase) {
SharedPreferences prefs = newBase.getSharedPreferences(Constants.APP_STATE.STATE_SHARED_PREFERENCES, MODE_PRIVATE);
String localeString = prefs.getString(Constants.APP_STATE.SAVED_LOCALE, Constants.DEFAULTS.DEFAULT_LOCALE);
Locale myLocale = new Locale(localeString);
Locale.setDefault(myLocale);
Configuration config = newBase.getResources().getConfiguration();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
config.setLocale(myLocale);
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.N){
Context newContext = newBase.createConfigurationContext(config);
super.attachBaseContext(newContext);
return;
}
} else {
config.locale = myLocale;
}
super.attachBaseContext(newBase);
getResources().updateConfiguration(config, getResources().getDisplayMetrics());
When user set wanted locale, what you want to do is to save it into some string in SharedPreferences and call recreate() of activity. This will then call attachBaseContext(Context context) and in this method proper locale will be set to configuration, then new context will be created with this configuration. After that, new context will be sent to super class which will update application context and proper locale will be shown.
It is also good because locale is automatically set when starting app next time.
回答2:
Change locale is a Configuration
which leads your acitivity restart. There are many other things have the same effect like orientation
, keyboardHidden
. Take care of your activity's states.
If restarting your activity requires that you recover large sets of data, re-establish a network connection, or perform other intensive operations, then a full restart due to a configuration change might be a slow user experience. Also, it might not be possible for you to completely restore your activity state with the Bundle that the system saves for you with the onSaveInstanceState() callback—it is not designed to carry large objects (such as bitmaps) and the data within it must be serialized then deserialized, which can consume a lot of memory and make the configuration change slow. In such a situation, you can alleviate the burden of reinitializing part of your activity by retaining a Fragment when your activity is restarted due to a configuration change. This fragment can contain references to stateful objects that you want to retain.
Not the best-practice, but you can handle it
<activity android:name=".MyActivity"
android:configChanges="locale"
android:label="@string/app_name">
Then in your Activity
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Do your stuff here
}
Remember to take care of your state. Using setRetainFragment(true)
is a good approach. Read this
回答3:
Yes your code is correct and if you want without refreshing the application
then In Your Application class you need to call this in onCreate()
method
String languageSelected = "en";//selected language
Locale myLocale = new Locale(languageSelected);
Resources res = getResources();
DisplayMetrics dm = res.getDisplayMetrics();
Configuration conf = res.getConfiguration();
conf.locale = myLocale;
res.updateConfiguration(conf, dm);
getActivity().onConfigurationChanged(conf);//Call this method
You need to perform this particular language to be selected on Application class.
来源:https://stackoverflow.com/questions/49380833/change-language-of-the-application-programmatically-without-refreshing-the-whole