How can I modify the summary of a ListPreference to the new \"Entry\" string selected by the user (not the entry value)
I suppouse its with setOnPreferenceChangeList
Just set the summary value to %s
in the xml description.
EDIT: I've tested it on several devices and it doesn't work really. That's strange because according to docs it must work: ListPreference.getSummary().
But it's possible to implement this functionality by oneself. The implementation requires to inherit from the ListPreference
class:
public class MyListPreference extends ListPreference {
public MyListPreference(final Context context) {
this(context, null);
}
public MyListPreference(final Context context, final AttributeSet attrs) {
super(context, attrs);
}
@Override
public CharSequence getSummary() {
final CharSequence entry = getEntry();
final CharSequence summary = super.getSummary();
if (summary == null || entry == null) {
return null;
} else {
return String.format(summary.toString(), entry);
}
}
@Override
public void setValue(final String value) {
super.setValue(value);
notifyChanged();
}
}
As you can see MyListPreference
has its own summary field which can contain formatting markers. And when a preference's value changes, Preference.notifyChanged()
method is called and it causes MyListPreference.getSummary()
method to be called from Preference.onBindView()
.
P.S.: This approach hasn't been tested sufficiently so it may contain errors.
i solved this problem with another and simple solution (https://gist.github.com/brunomateus/5617025):
public class ListPreferenceWithSummary extends ListPreference{
public ListPreferenceWithSummary(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ListPreferenceWithSummary(Context context) {
super(context);
}
@Override
public void setValue(String value) {
super.setValue(value);
setSummary(value);
}
@Override
public void setSummary(CharSequence summary) {
super.setSummary(getEntry());
}
}
This worked very fine on my GirgerBeard device. Even when is the first time running your app. Don't forget to provide default value on your xml prefence:
android:defaultValue="default value"
and set default values on your PreferenceActivity
or PrefenceFragment
:
PreferenceManager.setDefaultValues(this, R.xml.you pref file, false);
Referring to the accepted answer ( @Michael ), if you modify the MyListPreference to add an onPreferenceChangeListener:
public MyListPreference(final Context context, final AttributeSet attrs) {
super(context, attrs);
setOnPreferenceChangeListener(this);
}
and have the listener implementation return true:
public boolean onPreferenceChange(Preference preference, Object newValue) {
// Do other stuff as needed, e.g. setTitle()
return true;
}
the summary '%s' always resolves to the latest setting. Otherwise, it always has the default setting.
Don't forget to add implements:
public class MyListPreference extends ListPreference implements Preference.OnPreferenceChangeListener
I also faced this problem and I finally found a solution by using the value coming from the listener. In my example below (for a ListPreference), I first get the index of the value in the ListPreference array, then I retrieve the label of the value using this index:
passwordFrequencyLP.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
int newFrequency = Integer.valueOf(newValue.toString());
prefs.edit().putInt("settings_key_password_frequency", newFrequency).commit();
//get the index of the new value selected in the ListPreference array
int index = passwordFrequencyLP.findIndexOfValue(String.valueOf(newValue));
//get the label of the new value selected
String label = (String) passwordFrequencyLP.getEntries()[index];
passwordFrequencyLP.setSummary(label);
makeToast(getResources().getString(R.string.password_frequency_saved));
return true;
}
});
This little trick works well, I found many different possible solutions to this problem but only this one worked for me.
Simplest way in Kotlin
findPreference<ListPreference>(getString(R.string.pref_some_key)).apply {
summary = entry
setOnPreferenceChangeListener { _, newValue ->
summary = entries[entryValues.indexOf(newValue)]
return@setOnPreferenceChangeListener true
}
}
This is the most simplified way I have implemented. Just take the values given by the onPreferenceChange listener
ListPreference preference;
@Override
protected void onCreate(Bundle savedInstanceState) {
preference = (ListPreference)findPreference("myKey");
preference.setSummary(preferenceColorButtons.getEntry());
preference.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
ListPreference listPreference = (ListPreference)preference;
int id = 0;
for (int i = 0; i < listPreference.getEntryValues().length; i++)
{
if(listPreference.getEntryValues()[i].equals(newValue.toString())){
id = i;
break;
}
}
preference.setSummary(listPreference.getEntries()[id]);
return true;
}
});
}