ListPreference's summary text is not updated automatically whenever there is change in selection

android

Solution

This is a bug that existed on platforms prior to KITKAT (i.e. android-4.4_r0.7), and it is fixed by commit 94c02a1

The solution from @ilomambo works, but may not be the best one. I read through the source of `ListPreference` and came up with this solution:

File: ListPreferenceCompat.java

package com.example.yourapplication;

import android.content.Context;
import android.os.Build;
import android.preference.ListPreference;
import android.text.TextUtils;
import android.util.AttributeSet;

public class ListPreferenceCompat extends ListPreference {

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public ListPreferenceCompat(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public ListPreferenceCompat(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public ListPreferenceCompat(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ListPreferenceCompat(Context context) {
        super(context);
    }

    // NOTE:
    // The framework forgot to call notifyChanged() in setValue() on previous versions of android.
    // This bug has been fixed in android-4.4_r0.7.
    // Commit: platform/frameworks/base/+/94c02a1a1a6d7e6900e5a459e9cc699b9510e5a2
    // Time: Tue Jul 23 14:43:37 2013 -0700
    //
    // However on previous versions, we have to work around it by ourselves.
    @Override
    public void setValue(String value) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            super.setValue(value);
        } else {
            String oldValue = getValue();
            super.setValue(value);
            if (!TextUtils.equals(value, oldValue)) {
                notifyChanged();
            }
        }
    }
}

When you need to use `ListPreference` in xml, simply replace the tag to `com.example.yourapplication.ListPreferenceCompat`.

This works neatly on my Samsung S4 device running Android 4.3, and inside one of my production app.

Problem

Although it is being documented, by using `"%s"`, I can display selected value as summary, it doesn't work as expected. http://developer.android.com/reference/android/preference/ListPreference.html#getSummary%28%29 I am having the following `preferences.xml` ``` <?xml version="1.0" encoding="utf-8"?> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> <PreferenceCategory android:title="@string/preference_xxx_category"> <CheckBoxPreference android:title="@string/preference_xxx_mode_title" android:defaultValue="false" android:summary="@string/preference_xxx_mode_summary" android:key="xxxModePreference" /> </PreferenceCategory> <PreferenceCategory android:title="@string/preference_yyy_category"> <ListPreference android:title="@string/preference_yyy_mode_title" android:defaultValue="0" android:entries="@array/yyy" android:entryValues="@array/yyy_values" android:summary="%s" android:key="yyyModePreference" /> </PreferenceCategory> </PreferenceScreen> ``` and here is my `arrays.xml` ``` <?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="yyy"> <item>Display value 0</item> <item>Display value 1</item> </string-array> <string-array name="yyy_values"> <item>0</item> <item>1</item> </string-array> </resources> ``` What I expecting by having the following Java code to build a complete preference activity, with a check box and a list preference, the summary text of list preference can be updated automatically, whenever I perform selection. The summary text will toggle in between Display value 0 and Display value 1. ``` public class Preferences extends PreferenceActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.preferences); } } ``` However, I realize the summary text for list preference will not update automatically. Only when I perform tick/ untick on check box, only the whole activity will be invalidate and summary text for list preference will ONLY be updated. Hence, I have to revise my code as follow, which looks more cumbersome. ``` public class Preferences extends PreferenceActivity implements OnSharedPreferenceChangeListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.preferences); PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this); } @Override public void onResume() { super.onResume(); // Cumbersome way to make sure list preference's summary text is being updated. final String key = "yyyModePreference"; ListPreference listPreference = (ListPreference)findPreference(key); final String value = PreferenceManager.getDefaultSharedPreferences(this).getString(key, key); final int index = listPreference.findIndexOfValue(value); if (index >= 0) { final String summary = (String)listPreference.getEntries()[index]; listPreference.setSummary(summary); } } @Override public void onSharedPreferenceChanged(SharedPreferences options, String key) { // Cumbersome way to make sure list preference's summary text is being updated. if (key.equals("yyyModePreference")) { ListPreference listPreference = (ListPreference)findPreference(key); final String value = options.getString(key, key); final int index = listPreference.findIndexOfValue(value); if (index >= 0) { final String summary = (String)listPreference.getEntries()[index]; listPreference.setSummary(summary); } } } } ``` Is this a correct way? Is there any simplified way, to ensure ListPreference's summary text is always updated automatically whenever there is change in selection.

Original source

Related problems