I read a few times the official guide for this, and many other stuff, like questions on this site but I cant make mine work 100%
As of right now if I change the language in my list preference, the activity (SettingsActivity) will not update itself (like 1 out of 20 times, somehow it will, no idea why). After I press the back button, my MainActivity did not update either. But all my other activitys always show the correct language, and if I go back to the SettingsActivity it will be okay, same with the MainActivity, if I restart the app.
Relevant Parts:
MainActivity:
public class MainActivity extends Activity {
public static final String KEY_PREF_LANGUAGE = "pref_language";
@Override
protected void onCreate(Bundle savedInstanceState) {
...
PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
}
@Override
protected void onResume() {
super.onResume();
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
String languagePref_ID = sharedPref.getString(KEY_PREF_LANGUAGE, "2");
switch (languagePref_ID) {
case "1":
Locale localeEN = new Locale("en_US");
setLocale(localeEN);
break;
case "2":
Locale localeHU = new Locale("hu_HU");
setLocale(localeHU);
break;
}
}
public void setLocale(Locale locale) {
Locale.setDefault(locale);
Resources res = getResources();
DisplayMetrics dm = res.getDisplayMetrics();
Configuration conf = res.getConfiguration();
conf.locale = locale;
res.updateConfiguration(conf, dm);
//recreate();
//finish();
//startActivity(getIntent());
//if these are not commented, main activity wont show at start at all
}
SettingsActivity
public class SettingsActivity extends PreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
public static final String KEY_PREF_LANGUAGE = "pref_language";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getFragmentManager().beginTransaction()
.replace(android.R.id.content, new SettingsFragment())
.commit();
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.OnSharedPreferenceChangeListener listener =
new SharedPreferences.OnSharedPreferenceChangeListener() {
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
if (key.equals(KEY_PREF_LANGUAGE)) {
String languagePref_ID = prefs.getString(SettingsActivity.KEY_PREF_LANGUAGE, "");
switch (languagePref_ID) {
case "1":
Locale localeEN = new Locale("en_US");
setLocale(localeEN);
break;
case "2":
Locale localeHU = new Locale("hu_HU");
setLocale(localeHU);
break;
}
}
}
};
sharedPref.registerOnSharedPreferenceChangeListener(listener);
}
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (key.equals(KEY_PREF_LANGUAGE)) {
String languagePref_ID = sharedPreferences.getString(SettingsActivity.KEY_PREF_LANGUAGE, "2");
switch (languagePref_ID) {
case "1":
Locale localeEN = new Locale("en_US");
setLocale(localeEN);
break;
case "2":
Locale localeHU = new Locale("hu_HU");
setLocale(localeHU);
break;
}
}
//this doenst even get called but i need it for the implementation
}
public void setLocale(Locale locale) {
Locale.setDefault(locale);
Resources res = getResources();
DisplayMetrics dm = res.getDisplayMetrics();
Configuration conf = res.getConfiguration();
conf.locale = locale;
res.updateConfiguration(conf, dm);
recreate(); //tried like 4 ways to do this, nothing really worked
//finish();
//startActivity(getIntent());
}
}
SettingsFragment.java
public class SettingsFragment extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.preferences);
}
}
AndroidManifest.xml
android:configChanges="locale|orientation" //added to main and settings activity
I'm getting crazy over this, this is the best working state, but I know the activity lifecyle managment here is far from the best, when I try with those, I can't get it to work at all usually. How can I make this work so it actually updates on run time on all activities?
After your language is changed, you need to restart your current activity if you want to see it with changed language too. For example like this:
private void restartActivity() {
Intent intent = getIntent();
finish();
startActivity(intent);
}
Take a look at the best answer here How to refresh activity after changing language (Locale) inside application
In the end I made it work without the use of fragments. So there are some deprecated methods in here, I tried with fragments too, but no full succes (yet). This code refreshes SettingsActivity after a change always, and MainActivity updates itself too correctly.
MainActivity
public class MainActivity extends Activity {
public static final String KEY_PREF_LANGUAGE = "pref_language";
public String languagePref_ID;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
languagePref_ID = sharedPref.getString(KEY_PREF_LANGUAGE, "2");
switch (languagePref_ID) {
case "1":
Locale localeEN = new Locale("en_US");
setLocaleOnCreate(localeEN);
break;
case "2":
Locale localeHU = new Locale("hu_HU");
setLocaleOnCreate(localeHU);
break;
}
setContentView(R.layout.activity_main);
....
}
@Override
protected void onResume() {
super.onResume();
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
String languagePref_ID_RES = sharedPref.getString(KEY_PREF_LANGUAGE, "2");
if(!languagePref_ID.equals(languagePref_ID_RES)){
languagePref_ID_RES = languagePref_ID;
switch (languagePref_ID_RES) {
case "1":
Locale localeEN = new Locale("en_US");
setLocale(localeEN);
break;
case "2":
Locale localeHU = new Locale("hu_HU");
setLocale(localeHU);
break;
}
}
}
public void setLocaleOnCreate(Locale locale) {
Locale.setDefault(locale);
Resources res = getResources();
DisplayMetrics dm = res.getDisplayMetrics();
Configuration conf = res.getConfiguration();
conf.locale = locale;
res.updateConfiguration(conf, dm);
}
public void setLocale(Locale locale) {
Locale.setDefault(locale);
Resources res = getResources();
DisplayMetrics dm = res.getDisplayMetrics();
Configuration conf = res.getConfiguration();
conf.locale = locale;
res.updateConfiguration(conf, dm);
recreate();
//finish();
//startActivity(getIntent());
}
....
public void startSettingsActivity(View view) {
Intent intent = new Intent(this, SettingsActivity.class);
startActivity(intent);
}
}
SettingsActivity
public class SettingsActivity extends PreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
public static final String KEY_PREF_LANGUAGE = "pref_language";
public String languagePref_ID;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.OnSharedPreferenceChangeListener listener =
new SharedPreferences.OnSharedPreferenceChangeListener() {
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
if (key.equals(KEY_PREF_LANGUAGE)) {
languagePref_ID = prefs.getString(SettingsActivity.KEY_PREF_LANGUAGE, "2");
switch (languagePref_ID) {
case "1":
Locale localeEN = new Locale("en_US");
setLocale(localeEN);
break;
case "2":
Locale localeHU = new Locale("hu_HU");
setLocale(localeHU);
break;
}
}
}
};
sharedPref.registerOnSharedPreferenceChangeListener(listener);
addPreferencesFromResource(R.xml.preferences);
}
@Override
protected void onResume() {
super.onResume();
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}
@Override
protected void onPause() {
super.onPause();
getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
}
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (key.equals(KEY_PREF_LANGUAGE)) {
languagePref_ID = sharedPreferences.getString(SettingsActivity.KEY_PREF_LANGUAGE, "2");
switch (languagePref_ID) {
case "1":
Locale localeEN = new Locale("en_US");
setLocale(localeEN);
break;
case "2":
Locale localeHU = new Locale("hu_HU");
setLocale(localeHU);
break;
}
}
}
public void setLocale(Locale locale) {
Locale.setDefault(locale);
Resources res = getResources();
DisplayMetrics dm = res.getDisplayMetrics();
Configuration conf = res.getConfiguration();
conf.locale = locale;
res.updateConfiguration(conf, dm);
recreate();
}
}
来源:https://stackoverflow.com/questions/31183732/changing-language-in-run-time-with-preferences-android