Android List Preferences: have summary as selected value?

JavaAndroid

Java Problem Overview


I have a Preference activity which uses a List Preferences as defined by my XML file. How would I set the summary of the list activity to the value that is selected?

Java Solutions


Solution 1 - Java

The simplest way to do this is just to have Android do it for you. Assuming you want the summary to match the selected value, you can simply set the summary of the ListPreference to "%s" using either XML or the setSummary method in Java. For example:

<ListPreference
    android:key="pref_list"
    android:title="A list of preferences"
    android:summary="%s"
    android:entries="@array/pref_list_entries"
    android:entryValues="@array/pref_list_entries_values"
    android:defaultValue="0" />

Android will replace %s with the current string value of the preference, as displayed by the ListPreference's picker. The list's summary will also be set correctly when you enter the activity—you don't have to write any special code to set it up initially.

This also works with the AndroidX ListPreference.

I spent far too much time mucking with SharedPreferences listeners before I discovered this.

Solution 2 - Java

You can use OnPreferenceChangeListener to dynamically change the summary. The problem is that it gets the selected value (from android:entryValues), not the caption (android:entries). In the following code I used toString(), but the proper solution is to find the caption for the value. Anyways, the idea works:

public class Preferences extends PreferenceActivity {
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		addPreferencesFromResource(R.xml.your_prefs);
		
		ListPreference listPreference = (ListPreference) findPreference("preference_key");
		if(listPreference.getValue()==null) {
			// to ensure we don't get a null value
			// set first value by default
			listPreference.setValueIndex(0);
		}
		listPreference.setSummary(listPreference.getValue().toString());
		listPreference.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
			@Override
			public boolean onPreferenceChange(Preference preference, Object newValue) {
				preference.setSummary(newValue.toString());
				return true;
			}
		});
	}
}

Solution 3 - Java

I also wanted to achieve something similar, but the problem with https://stackoverflow.com/a/8155029/592025 is that, it shows the value for my preference (like 1, 2 3 etc). I want to show the entry (human readable string) corresponding to the selected value.

So I changed it this way and works the way I need it.

listPreference.setSummary(servicePreference.getEntry().toString());
listPreference.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
		
		@Override
		public boolean onPreferenceChange(Preference preference, Object newValue) {
			// Set the value as the new value
			listPreference.setValue(newValue.toString());
			// Get the entry which corresponds to the current value and set as summary
			preference.setSummary(listPreference.getEntry());
			return false;
		}
	});

The trick is to use getEntry() instead of getValue() and once the value is changed, to set the value explicitly and read back the entry.

Solution 4 - Java

I think that what you are looking for is much simple that you can think, add the following code line to your Preference item:

android:summary="%1$s"

So it will look something like this:

<ListPreference
            android:key="@string/pref_temp_key"
            android:title="@string/pref_temp_title"
            android:dialogTitle="@string/pref_temp_dialog_title"
            android:entries="@array/pref_tempUnit_entries"
            android:entryValues="@array/pref_tempUnit_entries"
            android:summary="%1$s"
            android:defaultValue="@string/pref_temp_default_value" />

Solution 5 - Java

So simple - just add the following property to your XML definition -

<ListPreference
...    
app:useSimpleSummaryProvider="true"
...
/>

Solution 6 - Java

First get a reference to the ListPreference in your onCreate. You can use findPreference(). For example:

ListPreference pref = (ListPreference) findPreference("thePreferencesKey");

Then, when you first load the Activity and whenever the preferences value is changed, use whatever method you want to get the value of the ListPreference and set the summary with:

pref.setSummary(theNewString);

Solution 7 - Java

This is the code I'm using, it does not call setValue manually, as I believe this is already done at a later stage.

Here is an example:

@Override
public boolean onPreferenceChange(Preference preference, Object value)
{
    String textValue = value.toString();

    ListPreference listPreference = (ListPreference) preference;
    int index = listPreference.findIndexOfValue(textValue);

    CharSequence[] entries = listPreference.getEntries();
    
    preference.setSummary(
                index >= 0
                        ? entries[index]
                        : null);

    return true;
}

Solution 8 - Java

This is exactly what I did and it works great. In the onSharedPreferenceChangeListener I just check the key of what is getting changed and then for ListPreferences convert it back to the Human readable (entry instead of entryValue) with the if statements. Pretty simple.

public class MyPreferences extends PreferenceFragment implements OnSharedPreferenceChangeListener{

public void onCreate(Bundle savedInstanceState){
	super.onCreate(savedInstanceState);
	addPreferencesFromResource(R.xml.preferences);
	context = getActivity();
	
	if (context == null){
		Log.e("error","context is null");
	}

	prefs = PreferenceManager.getDefaultSharedPreferences(context);
	myFrequencyList = (Preference)	findPreference("frequency_key");
    prefs.registerOnSharedPreferenceChangeListener(this);

}


@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
		String key) {
	
		if(key.equals("frequency_key")){
			    String freq = sharedPreferences.getString("frequency_key", "8k Hz");
			    if(freq.equals("8000")){
			    	freq = "8k Hz";
			    }
			    else if(freq.equals("16000")){
			    	freq = "16k Hz";
			    }
			    else if(freq.equals("22050")){
			    	freq = "22.05k Hz";
			    }
			    else if(freq.equals("44100")){
			    	freq = "44.1k Hz";
			    }
			    else if(freq.equals("48000")){
			    	freq = "48k Hz";
			    }
			    else{
			    	freq = "8k Hz";
			    }
				myFrequencyList.setSummary(freq);
		}

xml layout

 <ListPreference android:id="@+id/frequency_list"
        android:key="frequency_key"
        android:summary="8000"
        android:title="Sample Rate"
        android:defaultValue="8000"
        android:dialogTitle="Larger sample rates create better sound quality but larger file sizes."
        android:entries="@array/freq_titles"
        android:entryValues="@array/freq_values"
        />

xml array

<?xml version="1.0" encoding="utf-8"?>

<string-array name="freq_titles">
    <item>48k Hz</item>
    <item>44.1k Hz</item>
    <item>22.05k Hz</item>
    <item>16k Hz</item>
    <item>8k Hz</item>
</string-array>

<string-array name="freq_values">
    <item>48000</item>
    <item>44100</item>
    <item>22050</item>
    <item>16000</item>
    <item>8000</item>
</string-array>



Solution 9 - Java

Here's an expanded version of midhunhk's answer that addresses the helpful "android:summary" string as well

		// Retrieve & populate flash modes
		List<String> flashmodes = params.getSupportedFlashModes();
		if (flashmodes != null) {
			final ListPreference lp = (ListPreference) findPreference("flash_list");
			final String lp_basesummary = "Set the Flash mode. The default is 'auto'";

			lp.setEntries(flashmodes.toArray(new CharSequence[flashmodes.size()]));
			lp.setEntryValues(flashmodes.toArray(new CharSequence[flashmodes.size()]));
			// If there's only one option, make it the default
			if (flashmodes.size() == 1)
				lp.setValueIndex(0);

			lp.setSummary(lp_basesummary + " [" + lp.getEntry() + "]");

			lp.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {

				@Override
				public boolean onPreferenceChange(Preference preference, Object newValue) {
					// Set the value as the new value
					lp.setValue(newValue.toString());
					// Get the entry which corresponds to the current value
					// and set as summary
					preference.setSummary(lp_basesummary + " [" + lp.getEntry() + "]");
					return false;
				}
			});
		} else {
			// Remove the preference
			((PreferenceGroup) findPreference("camera_preference")).removePreference(findPreference("flash_list"));
		}

		// Retrieve & populate focus modes
		List<String> focusmodes = params.getSupportedFocusModes();
		if (focusmodes != null) {
			final ListPreference lp = (ListPreference) findPreference("focus_mode_list");
			final String lp_basesummary = "Set the Focus mode. The default is 'auto'";
...

And, just to be clear, android:summary is removed from the related xml.

Solution 10 - Java

And here's one way to deal with the Ringtone preference's summary update following a user selection.

	final SharedPreferences preference = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());

	final RingtonePreference rp_shuttle = (RingtonePreference) findPreference("shuttle_tone");
	rp_shuttle.setSummary(RingtoneManager
			.getRingtone(getApplicationContext(), Uri.parse(preference.getString("shuttle_tone", "DEFAULT_SOUND")))
			.getTitle(this));

	rp_shuttle.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {

		public boolean onPreferenceChange(Preference mypreference, Object newValue) {
			rp_shuttle.setSummary(RingtoneManager.getRingtone(getApplicationContext(), Uri.parse(newValue + ""))
					.getTitle(getApplicationContext()));

			return true;
		}
	})

Solution 11 - Java

You hava a method bindPreferenceSummaryToValue on your PreferenceActivity,

you can easily add the summary to the list doing like this:

private static void bindPreferenceSummaryToValue(Preference preference) {
    preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener);

    sBindPreferenceSummaryToValueListener.onPreferenceChange(preference,
            PreferenceManager
                    .getDefaultSharedPreferences(preference.getContext())
                    .getString(preference.getKey(), ""));
}

On yout OnCreate method you call the bind function like this:

bindPreferenceSummaryToValue(findPreference(getString(R.string.KEY_OF_THE_LIST)));

You can easily add others summary on the same way:

bindPreferenceSummaryToValue(findPreference(getString(R.string.KEY_1)));
bindPreferenceSummaryToValue(findPreference(getString(R.string.KEY_2)));
bindPreferenceSummaryToValue(findPreference(getString(R.string.KEY_3)));

Solution 12 - Java

under onCreatePreferences do this::

SharedPreferences sharedPreferences =getPreferenceScreen().getSharedPreferences();
PreferenceScreen prefScreen = getPreferenceScreen();
int count = prefScreen.getPreferenceCount();

for (int i = 0; i < count; i++) {
  Preference p = prefScreen.getPreference(i);
    if (p instanceof ListPreference) {
       String value = sharedPreferences.getString(p.getKey(), "");
       ListPreference listPreference = (ListPreference) preference;
       int prefIndex = listPreference.findIndexOfValue(stringValue);
       if (prefIndex >= 0) {
            preference.setSummary(listPreference.getEntries()[prefIndex]);
      }
    }
 }  

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionFran FitzpatrickView Question on Stackoverflow
Solution 1 - JavaGeorge HilliardView Answer on Stackoverflow
Solution 2 - JavaAxelView Answer on Stackoverflow
Solution 3 - JavamidhunhkView Answer on Stackoverflow
Solution 4 - Java42GeekView Answer on Stackoverflow
Solution 5 - JavaNati DyksteinView Answer on Stackoverflow
Solution 6 - JavacottonBallPawsView Answer on Stackoverflow
Solution 7 - JavaMobergView Answer on Stackoverflow
Solution 8 - JavaJordan HochstetlerView Answer on Stackoverflow
Solution 9 - JavaRudyFView Answer on Stackoverflow
Solution 10 - JavaRudyFView Answer on Stackoverflow
Solution 11 - JavaMarcio MontenegroView Answer on Stackoverflow
Solution 12 - JavaDerrick NjeruView Answer on Stackoverflow