I have prepared a simple test case at GitHub for my question and have a feeling, that only few lines of code are missing to make it working.
In an Android app I have 1 activity (MainActivity.java) and 2 fragments (MainFragment.java and PrefFragment.java) - and when I change values in the preferences fragment, they are not saved.
Also the default values are not loaded and the summaries not updated:
Here is my PrefFragment where I register a shared prefs listener - in order to update the summaries - but for some reason it is never called:
public class PrefFragment extends PreferenceFragment
implements OnSharedPreferenceChangeListener {
public static final String BOOL_1 = "bool_1";
public static final String STR_1 = "str_1";
public static final String STR_2 = "str_2";
private CheckBoxPreference mBool1;
private EditTextPreference mStr1;
private EditTextPreference mStr2;
private SharedPreferences mPrefs;
private Editor mEditor;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(false);
addPreferencesFromResource(R.xml.preferences);
mBool1 = (CheckBoxPreference) findPreference(BOOL_1);
mStr1 = (EditTextPreference) findPreference(STR_1);
mStr2 = (EditTextPreference) findPreference(STR_2);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
mPrefs = PreferenceManager.getDefaultSharedPreferences(activity);
mEditor = mPrefs.edit();
mPrefs.registerOnSharedPreferenceChangeListener(this);
}
#Override
public void onDetach() {
super.onDetach();
mPrefs.unregisterOnSharedPreferenceChangeListener(this);
}
#Override
public void onSharedPreferenceChanged(SharedPreferences prefs,
String key) {
Log.d("onSharedPreferenceChanged", key); // XXX is never called
if (BOOL_1.equals(key)) {
boolean bool1 = prefs.getBoolean(key, false);
mBool1.setSummary(bool1 ? "Enabled" : "Disabled");
} else if (STR_1.equals(key)) {
String str1 = prefs.getString(key, "");
mStr1.setSummary(str1);
} else if (STR_2.equals(key)) {
String str2 = prefs.getString(key, "");
mStr2.setSummary(str2);
}
}
}
And here is preference.xml:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<PreferenceCategory
android:title="Category 1"
android:key="category_1">
<CheckBoxPreference
android:key="bool_1"
android:title="Boolean 1"
android:summary="XXX how to set this? XXX"
android:defaultValue="false" />
<EditTextPreference
android:dependency="bool_1"
android:key="str_1"
android:title="String 1"
android:summary="XXX how to set this? XXX"
android:defaultValue="change me" />
<EditTextPreference
android:dependency="bool_1"
android:key="str_2"
android:title="String 2"
android:summary="XXX how to set this? XXX"
android:defaultValue="change me too" />
</PreferenceCategory>
</PreferenceScreen>
So my question is how to handle (load, save) values in PreferenceFragment? Do I really have to extend EditTextPreference and implement onDialogClosed method in my custom class? This seems like an overkill approach to me.
Ok, the following seems to work in PrefFragment.java:
#Override
public void onResume() {
super.onResume();
SharedPreferences prefs = getPreferenceManager().getSharedPreferences();
// CHANGE 1: load saved values to set the summaries
onSharedPreferenceChanged(prefs, BOOL_1);
onSharedPreferenceChanged(prefs, STR_1);
onSharedPreferenceChanged(prefs, STR_2);
// CHANGE 2: register shared prefs listener in onResume
prefs.registerOnSharedPreferenceChangeListener(this);
}
#Override
public void onPause() {
super.onPause();
SharedPreferences prefs = getPreferenceManager().getSharedPreferences();
prefs.unregisterOnSharedPreferenceChangeListener(this);
}
Related
I'm struggling to figure out how to show the preference in the preference activity. I'm simply trying to show the high score and i keep getting the same 345 value show up. I have confirmed in debugging that the new high score is saved . Here is all my code.
preferences.xml
<Preference
android:title="High Score"
android:selectable="false"
android:defaultValue="0"
android:key="#string/pref_highest_score"/>
HighScoreActivity.java
public class HighScoreActivity extends PreferenceActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getFragmentManager().beginTransaction()
.replace(android.R.id.content, new HighScoreFragment()).commit();
}
public static class HighScoreFragment extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener {
#Override
public void onResume(){
super.onResume();
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
}
}
}
strings.xml
<!-- High Score settings -->
<string name="pref_highest_score">345</string>
<string name="title_activity_high_score">High Score</string>
MainActivity.java
preferences = PreferenceManager.getDefaultSharedPreferences(context);
Assets.highScore = preferences.getInt(context.getString(R.string.pref_highest_score), 1);
editor = preferences.edit();
editor.putInt(context.getString(R.string.pref_highest_score), currentPoints );
editor.apply();
It's because your preference screen does not actually gets the value of pref_highest_score. You should find the preference and call Preference.setSummary(). Like:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
// Gets the preference defined in XML
Preference p = findPreference("#string/pref_highest_score");
// Sets the summary of the preference to the high score
p.setSummary(
String.valueOf(preferences.getInt(context.getString(R.string.pref_highest_score), 1))
);
}
where preferences is PreferenceManager.getDefaultSharedPreferences(context).
And in your XML, specify an id of the preference:
<Preference
android:key="#string/pref_highest_score"
android:title="High Score"
android:selectable="false"
android:defaultValue="0"/>
i have setup an onpreference click listener for a preference but it fails to fire even though the preference is found by the find preference command.
Activity
public class PreferenceActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Display the fragment as the main content
setContentView(R.layout.activity_preference);
if (savedInstanceState == null) {
getFragmentManager().beginTransaction()
.replace(R.id.settings, new SettingsFragment())
.commit();
}
}
public static class SettingsFragment extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener {
Context context;
private final String DOB = "date";
private SharedPreferences prefs;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
context = getActivity().getApplicationContext();
Preference dob = findPreference(DOB);
Log.i("test", dob.getKey() + "");
dob.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
#Override
public boolean onPreferenceClick(Preference preference) {
Log.i("test", "2");
return false;
}
});
}
#Override
public void onPause() {
super.onPause();
getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
}
#Override
public void onResume() {
super.onResume();
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}
}
}
The preference xml
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory android:title="My Account">
<EditTextPreference
android:key="profile_name"
android:summary="Taylor Swift"
android:title="Username" />
<Preference
android:key="date"
android:summary="N.A."
android:title="#string/date" />
</PreferenceCategory>
</PreferenceScreen>
The log output for "test" correctly displays the key of the preference but the log within the onclick never fires.
I've created simple project with your code and everything seems to be working fine.
Log.i("test", "2");
is being called when I click "Date" field.
I have those preference:
<xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<CheckBoxPreference
android:key="pk1"
android:title="#string/pt1"
android:summary="#string/pt1s"
android:defaultValue="false" />
<CheckBoxPreference
android:key="pk2"
android:title="#string/pt2"
android:defaultValue="false" />
<ListPreference
android:key="pk3"
android:title="#string/pt3"
android:dialogTitle="#string/pt3"
android:entries="#array/fontsi"
android:entryValues="#array/fontsiv"
android:defaultValue="0" />
<Preference
android:key="pkb"
android:title="#string/ptb" />
</PreferenceScreen>
And the settings activity:
public class SettingsActivity extends PreferenceActivity {
SharedPreferences.OnSharedPreferenceChangeListener lst;
SharedPreferences prf;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
prf = getPreferenceScreen().getSharedPreferences();
lst = new SharedPreferences.OnSharedPreferenceChangeListener() {
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
Log.i("SettingsActivity","!any preference changen!");
if (key.equals("pk1")) { Log.i("SettingsActivity","!pref PK1 called!"); } }
else if (key.equals("pkb")) { Log.i("SettingsActivity","!pref PKB called!"); }
prf.registerOnSharedPreferenceChangeListener(lst);
}
#Override
protected void onResume() {
super.onResume();
prf.registerOnSharedPreferenceChangeListener(lst); }
#Override
protected void onPause() {
super.onPause();
prf.unregisterOnSharedPreferenceChangeListener(lst); }
...
}
The listener works with all the preferences but e custom preference (the last one, pkb as key)!
That i want to use as a back button.
Anybody knows why ?
Obviously your preference doesn't change any preferences.
Since it doesn't do anything, OnSharedPreferenceChangeListener ignores it.
A possible solution would be to set a clickListener to it like this:
findPreference("pkb").setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
#Override
public boolean onPreferenceClick(Preference preference) {
Log.i("SettingsActivity", "!pref PKB called!");
return false;
}
});
My trouble is that when I'm trying to select an item from listpreference, the summary changes to the selected array key from array settings_listofitems_keys.
But I want to set the summary to a user readable format from array settings_listofitems_values on layout and at the same time save that value from settings_listofitems_keys as a parameter in preferences.
Xml arrays file:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="settings_listofitems_values">
<item>Green</item>
<item>Orange</item>
</string-array>
<string-array name="settings_listofitems_keys">
<item>1</item>
<item>2</item>
</string-array>
</resources>
Xml layout file:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<PreferenceCategory android:title="#string/settings_select_horo" >
<ListPreference
android:defaultValue="#string/settings_selectitem"
android:key="preferenceitem"
android:entries="#array/settings_listofitems_values"
android:summary="#string/settings_plsselect"
android:entryValues="#array/settings_listofitems_keys"
android:title="#string/settings_plsselect" />
</PreferenceCategory>
</PreferenceScreen>
Code:
public class UserSettingActivity extends PreferenceActivity implements
OnPreferenceChangeListener {
private static final String APP_PREFERENCES = "mypref";
#SuppressWarnings("deprecation")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.layout.activity_preferences);
SharedPreferences settings = getSharedPreferences(APP_PREFERENCES,
Context.MODE_PRIVATE);
SharedPreferences.Editor editor = settings.edit();
ListPreference myid = (ListPreference)
findPreference("preferenceitem");
myid.setOnPreferenceChangeListener(this);
editor.commit();
}
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
preference.setSummary(newValue.toString());
return true;
}
}
Any help is highly appreciated. I can also be a good example for newbies =)
All this with editors and commits and preferences does nothing - change it !
public class UserSettingActivity extends PreferenceActivity implements
OnPreferenceChangeListener {
#SuppressWarnings("deprecation")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.layout.activity_preferences);
ListPreference myid = (ListPreference)
findPreference("preferenceitem");
myid.setOnPreferenceChangeListener(this);
}
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
preference.setSummary(newValue.toString()); // that's ok
return true;
}
}
Here is your issue - you must delete the summary line:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<PreferenceCategory android:title="#string/settings_select_horo" >
<ListPreference
android:defaultValue="#string/settings_selectitem"
android:key="preferenceitem"
android:entries="#array/settings_listofitems_values"
<!-- android:summary="#string/settings_plsselect"-->
android:entryValues="#array/settings_listofitems_keys"
android:title="#string/settings_plsselect" />
</PreferenceCategory>
</PreferenceScreen>
Instead of
public class UserSettingActivity extends PreferenceActivity implements OnPreferenceChangeListener {
private static final String APP_PREFERENCES = "mypref";
#SuppressWarnings("deprecation")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.layout.activity_preferences);
SharedPreferences settings = getSharedPreferences(APP_PREFERENCES, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = settings.edit();
ListPreference myid = (ListPreference) findPreference("preferenceitem");
myid.setOnPreferenceChangeListener(this);
editor.commit();
}
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
preference.setSummary(newValue.toString());
return true;
}
Try using this:
public class UserSettingActivity extends PreferenceActivity {
private static final String APP_PREFERENCES = "mypref";
#SuppressWarnings("deprecation")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.layout.activity_preferences);
ListPreference myid = (ListPreference) findPreference("preferenceitem");
myid.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
int index = ((ListPreference) preference).findIndexOfValue(newValue.toString());
preference.setSummary(index >= 0 ? ((ListPreference) preference).getEntries()[index] : null);
return true;
}
});
}
}
Hope this helps :)
I have my prefence options like this:
public class Opciones extends PreferenceActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.opciones);
SharedPreferences sp = getPreferenceScreen().getSharedPreferences();
EditTextPreference editTextPref = (EditTextPreference) findPreference( "opcCodigo" );
editTextPref.setSummary(sp.getString("opcCodigo", ""));
EditTextPreference editTextPref2 = (EditTextPreference) findPreference( "opcUrl" );
editTextPref2.setSummary(sp.getString("opcUrl", ""));
}
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
Preference pref = findPreference(key);
if (pref instanceof EditTextPreference) {
EditTextPreference etp = (EditTextPreference) pref;
pref.setSummary(etp.getText());
}
}
}
The fact is that when I change the data, the fields are not refreshed, I have to close the activity and launch it again to see them.
Whats I´m missing?
Thanks in advance
Implement OnPreferenceChangeListener and override the following method.
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
//newValue is the edited data
if(editTextPref == preference) editTextPref.setSummary(newValue);
else editTextPref2.setSummary(newValue);
}
Try this:
1. Add OnSharedPreferenceChangeListner
public class Opciones extends PreferenceActivity implements
OnSharedPreferenceChangeListener
2. And Override method onSharedPreferenceChanged
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,String key){
// ...
}