How do I display the current value of an Android P

2019-01-01 11:34发布

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).

30条回答
时光乱了年华
2楼-- · 2019-01-01 11:57

The concise solution by 1 line of code:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    addPreferencesFromResource(R.xml.preferences);

    bindPreferenceSummaryToValue(findPreference("mySetting"));

    // initialize summary
    sBindPreferenceSummaryToValueListener.onPreferenceChange(findPreference("mySetting"), 
        ((ListPreference) findPreference("mySetting")).getEntry());
}
查看更多
弹指情弦暗扣
3楼-- · 2019-01-01 11:58

FYI:

findPreference(CharSequence key)
This method was deprecated in API level 11. This function is not relevant
for a modern fragment-based PreferenceActivity.

All the more reason to look at the very slick Answer of @ASD above (source found here) saying to use %s in android:summary for each field in preferences.xml. (Current value of preference is substituted for %s.)

enter image description here

<ListPreference
 ...        
 android:summary="Length of longest word to return as match is %s"
 ...
 />
查看更多
后来的你喜欢了谁
4楼-- · 2019-01-01 11:58

To set the summary of a ListPreference to the value selected in a dialog you could use this code:

package yourpackage;

import android.content.Context;
import android.util.AttributeSet;

public class ListPreference extends android.preference.ListPreference {

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

    protected void onDialogClosed(boolean positiveResult) {
        super.onDialogClosed(positiveResult);
        if (positiveResult) setSummary(getEntry());
    }

    protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
        super.onSetInitialValue(restoreValue, defaultValue);
        setSummary(getEntry());
    }
}

and reference the yourpackage.ListPreference object in your preferences.xml remembering to specify there your android:defaultValue as this triggers the call to onSetInitialValue().

If you want you can then modify the text before calling setSummary() to whatever suits your application.

查看更多
荒废的爱情
5楼-- · 2019-01-01 11:59

Actually, CheckBoxPreference does have the ability to specify a different summary based on the checkbox value. See the android:summaryOff and android:summaryOn attributes (as well as the corresponding CheckBoxPreference methods).

查看更多
怪性笑人.
6楼-- · 2019-01-01 12:00

Thanks for this tip!

I have one preference screen and want to show the value for each list preference as the summary.

This is my way now:

public class Preferences extends PreferenceActivity implements OnSharedPreferenceChangeListener {

@Override
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.preferences);
}

@Override
protected void onResume() {
    super.onResume();

    // Set up initial values for all list preferences
    Map<String, ?> sharedPreferencesMap = getPreferenceScreen().getSharedPreferences().getAll();
    Preference pref;
    ListPreference listPref;
    for (Map.Entry<String, ?> entry : sharedPreferencesMap.entrySet()) {
        pref = findPreference(entry.getKey());
        if (pref instanceof ListPreference) {
            listPref = (ListPreference) pref;
            pref.setSummary(listPref.getEntry());
        }
    }

    // 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) {
    Preference pref = findPreference(key);

    if (pref instanceof ListPreference) {
        ListPreference listPref = (ListPreference) pref;
        pref.setSummary(listPref.getEntry());
    }
}

This works for me, but I'm wondering what is the best solution (performance, stability, scalibility): the one Koem is showing or this one?

查看更多
牵手、夕阳
7楼-- · 2019-01-01 12:01

Maybe like ListPreference: Modify getSummary to get what you want:

package your.package.preference;

import android.content.Context;
import android.util.AttributeSet;

public class EditTextPreference extends android.preference.EditTextPreference{
        public EditTextPreference(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        }

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

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

        @Override
        public CharSequence getSummary() {
            if(super.getSummary() == null) return null;

            String summary = super.getSummary().toString();
            return String.format(summary, getText());
        }
    }

And use this in your xml:

<your.package.EditTextPreference
                android:key="pref_alpha"
                android:summary="Actual value: %s"
                android:title="Title"
                android:defaultValue="default"
                />

So you are able to write a summary with %s instead of the actual value.

查看更多
登录 后发表回答