I've implemented a Settings screen in my android app, having a ListPreference to allow users to choose the language. It works fine when an item of the list is selected, recreating the activity and translating the literals automatically, but when the cancel button is pressed, if the user tries to change the language again, the effect is not visible, but when the settings screen is closed, the literals have been perfectly translated.
That is my SettingsActivity
with the inner class modelling tha Fragment I am using:
public class SettingsActivity extends PreferenceActivity {
/** Preferences fields */
private static final String PREF_LANGUAGE = "pref_language";
/**
* Method called when the application is been started
*
* @param savedInstanceState the saved instance state
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
final String PREF_LANGUAGE = "pref_language";
super.onCreate(savedInstanceState);
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
String language = "en";
if (Locale.getDefault().getLanguage().equals("es")) {
language = "es";
}
String languagePref = settings.getString(PREF_LANGUAGE, language);
Locale locale = new Locale(languagePref);
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getResources().updateConfiguration(config, getResources().getDisplayMetrics());
setContentView(R.layout.settings_activity);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.OnSharedPreferenceChangeListener prefListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
/**
* Method triggered when a shared preference changes
*
* @param sharedPreferences is the object which represents the shared preferences
* @param key is the key of the preference changed
*/
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
switch (key) {
case PREF_LANGUAGE:
Locale locale = new Locale(sharedPreferences.getString(key, ""));
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getResources().updateConfiguration(config, getResources().getDisplayMetrics());
recreate();
break;
}
}
};
prefs.registerOnSharedPreferenceChangeListener(prefListener);
}
/**
* Class which represents the fragment for the settings screen
*/
public static class GeograppPreferenceFragment extends PreferenceFragment {
/**
* Method triggered when the fragment is created
*
* @param savedInstanceState is the state of the fragment
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(settings);
SharedPreferences settings = getPreferenceManager().getSharedPreferences();
String language = "en";
if (Locale.getDefault().getLanguage().equals("es")) {
language = "es";
}
String languagePref = settings.getString(PREF_LANGUAGE, language);
getPreferenceManager().findPreference(PREF_LANGUAGE).setDefaultValue(languagePref);
}
}
}
The preference xml is:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:title="@string/settings_display" />
<ListPreference
android:key="pref_language"
android:title="@string/settings_language_title"
android:summary="@string/settings_language_summary"
android:entries="@array/language_options"
android:entryValues="@array/language_values" />
</PreferenceScreen>
Finally I could solve it with defining an individual listener to that preference with the instruction setOnPreferenceChangeListener
and deleting the OnSharedPreferenceChangeListener
in the OnCreate
method