How do I display the current value of an Android Preference in the Preference summary?
This must come up very often.
When the user is editing preferences in an Android app, I'd like them to be able to see the currently set value of the preference in the Preference
summary.
Example: if I have a Preference setting for "Discard old messages" that specifies the number of days after which messages need to be cleaned up. In the PreferenceActivity
I'd like the user to see:
"Discard old messages" <- title
"Clean up messages after x days" <- summary where x is the current Preference value
Extra credit: make this reusable, so I can easily apply it to all my preferences regardless of their type (so that it work with EditTextPreference, ListPreference etc. with minimal amount of coding).
Solution 1:
There are ways to make this a more generic solution, if that suits your needs.
For example, if you want to generically have all list preferences show their choice as summary, you could have this for your onSharedPreferenceChanged
implementation:
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
Preference pref = findPreference(key);
if (pref instanceof ListPreference) {
ListPreference listPref = (ListPreference) pref;
pref.setSummary(listPref.getEntry());
}
}
This is easily extensible to other preference classes.
And by using the getPreferenceCount
and getPreference
functionality in PreferenceScreen
and PreferenceCategory
, you could easily write a generic function to walk the preference tree setting the summaries of all preferences of the types you desire to their toString
representation
Solution 2:
Here is my solution... FWIW
package com.example.PrefTest;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.os.Bundle;
import android.preference.EditTextPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceGroup;
import android.preference.PreferenceManager;
public class Preferences extends PreferenceActivity implements
OnSharedPreferenceChangeListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
PreferenceManager.setDefaultValues(Preferences.this, R.xml.preferences,
false);
initSummary(getPreferenceScreen());
}
@Override
protected void onResume() {
super.onResume();
// Set up a listener whenever a key changes
getPreferenceScreen().getSharedPreferences()
.registerOnSharedPreferenceChangeListener(this);
}
@Override
protected void onPause() {
super.onPause();
// Unregister the listener whenever a key changes
getPreferenceScreen().getSharedPreferences()
.unregisterOnSharedPreferenceChangeListener(this);
}
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) {
updatePrefSummary(findPreference(key));
}
private void initSummary(Preference p) {
if (p instanceof PreferenceGroup) {
PreferenceGroup pGrp = (PreferenceGroup) p;
for (int i = 0; i < pGrp.getPreferenceCount(); i++) {
initSummary(pGrp.getPreference(i));
}
} else {
updatePrefSummary(p);
}
}
private void updatePrefSummary(Preference p) {
if (p instanceof ListPreference) {
ListPreference listPref = (ListPreference) p;
p.setSummary(listPref.getEntry());
}
if (p instanceof EditTextPreference) {
EditTextPreference editTextPref = (EditTextPreference) p;
if (p.getTitle().toString().toLowerCase().contains("password"))
{
p.setSummary("******");
} else {
p.setSummary(editTextPref.getText());
}
}
if (p instanceof MultiSelectListPreference) {
EditTextPreference editTextPref = (EditTextPreference) p;
p.setSummary(editTextPref.getText());
}
}
}
Solution 3:
Android documentation says one can use a String formatting marker in getSummary()
:
If the summary has a String formatting marker in it (i.e. "%s" or "%1$s"), then the current entry value will be substituted in its place.
Simply specifying android:summary="Clean up messages after %s days"
in ListPreference xml declaration worked for me.
Note: This only works for ListPreference
.