这个问题肯定经常出现。

当用户在Android应用程序中编辑首选项时,我希望他们能够在首选项摘要中看到当前设置的首选项值。

例如:如果我有“丢弃旧消息”的首选项设置,该设置指定了需要清理消息的天数。在PreferenceActivity中,我想让用户看到:

"丢弃旧消息" <- title

“x天后清理消息”<- summary,其中x是当前首选项值

额外的学分:使此可重用,所以我可以很容易地将它应用到我的所有首选项,而不管它们的类型(使它与EditTextPreference, ListPreference等工作,只需最少的编码)。


当前回答

因为我使用了一个自定义PreferenceDataStore,我不能添加一个监听器到一些SharedPreference,所以我不得不写一个有点hack的解决方案,监听每个偏好:

class SettingsFragment : PreferenceFragmentCompat(), Preference.OnPreferenceChangeListener {
    private val handler: Handler by lazy { Handler(Looper.getMainLooper()) }

    override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
        preferenceManager.preferenceDataStore = prefs
        addPreferencesFromResource(R.xml.app_preferences)
        onPreferenceChange(preferenceScreen, null)
    }

    override fun onPreferenceChange(preference: Preference, newValue: Any?): Boolean {
        preference.onPreferenceChangeListener = this

        when (preference) {
            is PreferenceGroup -> for (i in 0 until preference.preferenceCount) {
                onPreferenceChange(preference.getPreference(i), null)
            }
            is ListPreference -> {
                if (preference.value == null) {
                    preference.isPersistent = false
                    preference.value = Preference::class.java.getDeclaredField("mDefaultValue")
                            .apply { isAccessible = true }
                            .get(preference).toString()
                    preference.isPersistent = true
                }

                postPreferenceUpdate(Runnable { preference.summary = preference.entry })
            }
        }
        return true
    }

    /**
     * We can't directly update the preference summary update because [onPreferenceChange]'s result
     * is used to decide whether or not to update the pref value.
     */
    private fun postPreferenceUpdate(r: Runnable) = handler.post(r)
}

其他回答

谢谢Reto的详细解释!

为了对大家有所帮助,我不得不修改Reto Meier提出的代码,使其与Android 1.5的SDK兼容

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

    // Setup the initial values
    mListPreference.setSummary("Current value is " + mListPreference.getEntry().toString()); 

    // Set up a listener whenever a key changes            
    ...
}

同样的变化适用于回调函数onSharedPreferenceChanged(SharedPreferences SharedPreferences, String key)

欢呼,

克里斯

public class ProfileManagement extends PreferenceActivity implements
OnPreferenceChangeListener {
    EditTextPreference screenName;
    ListPreference sex;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            addPreferencesFromResource(R.layout.profile_management);

            screenName = (EditTextPreference) findPreference("editTextPref");
            sex = (ListPreference) findPreference("sexSelector");

            screenName.setOnPreferenceChangeListener(this);
            sex.setOnPreferenceChangeListener(this);

    }   

    @Override
    public boolean onPreferenceChange(Preference preference, Object newValue) {
        preference.setSummary(newValue.toString());
        return true;
    }
}

FYI:

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

更有理由看看上面@ASD的非常圆滑的答案(来源在这里找到),它说在android:summary中对preferences.xml中的每个字段使用%s。(首选项的当前值替换为%s。)

<ListPreference
 ...        
 android:summary="Length of longest word to return as match is %s"
 ...
 />

在我花了几个小时来解决这样的问题后,我实现了以下代码:

[更新:最终版本列表]

public class MyPreferencesActivity extends PreferenceActivity {
    ...
    ListPreference m_updateList;
    ...
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.preferences);

        m_updateList = (ListPreference) findPreference(getString(R.string.pref_update_interval_key));
        String currentValue = m_updateList.getValue();
        if (currentValue == null) {
            m_updateList.setValue((String)m_updateList.getEntryValues()[DEFAULT_UPDATE_TIME_INDEX]);
            currentValue = m_updateList.getValue();
        }
        updateListSummary(currentValue);    

        m_updateList.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
            @Override
            public boolean onPreferenceChange(Preference preference, Object newValue) {
                updateListSummary(newValue.toString());
                return true;
            }       
        });     
    }

    private void updateListSummary(String newValue) {
        int index = m_updateList.findIndexOfValue(newValue);
        CharSequence entry = m_updateList.getEntries()[index];
        m_updateList.setSummary(entry);
    }
}

这是唯一对我有效的解决方法。在我尝试子类从ListPreferences和实现android:summary="bla bla bla %s"。既不工作。

我的解决方案是创建一个自定义的EditTextPreference,像这样在XML中使用:EditTextPreference android:title="示例title " />

EditTextPreference.java: -

package com.example;

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, null);
    }

    @Override
    protected void onDialogClosed(boolean positiveResult)
    {
        super.onDialogClosed(positiveResult);

        setSummary(getSummary());
    }

    @Override
    public CharSequence getSummary()
    {
        return getText();
    }
}