这个问题肯定经常出现。

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

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

"丢弃旧消息" <- title

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

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


当前回答

谢谢你的建议!

我有一个首选项屏幕,并希望显示每个列表首选项的值作为摘要。

这就是我现在的方式:

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());
    }
}

这对我来说是可行的,但我想知道最好的解决方案(性能、稳定性、可伸缩性)是Koem展示的那个还是这个?

其他回答

如果你使用PreferenceFragment,这就是我解决它的方法。这是不言而喻的。

public static class SettingsFragment extends PreferenceFragment implements OnSharedPreferenceChangeListener {
    @Override
    public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      addPreferencesFromResource(R.xml.settings);
      getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
    }

    @Override
    public void onResume() {
      super.onResume();
      for (int i = 0; i < getPreferenceScreen().getPreferenceCount(); ++i) {
        Preference preference = getPreferenceScreen().getPreference(i);
        if (preference instanceof PreferenceGroup) {
          PreferenceGroup preferenceGroup = (PreferenceGroup) preference;
          for (int j = 0; j < preferenceGroup.getPreferenceCount(); ++j) {
            Preference singlePref = preferenceGroup.getPreference(j);
            updatePreference(singlePref, singlePref.getKey());
          }
        } else {
          updatePreference(preference, preference.getKey());
        }
      }
    }

    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
      updatePreference(findPreference(key), key);
    }

    private void updatePreference(Preference preference, String key) {
      if (preference == null) return;
      if (preference instanceof ListPreference) {
        ListPreference listPreference = (ListPreference) preference;
        listPreference.setSummary(listPreference.getEntry());
        return;
      }
      SharedPreferences sharedPrefs = getPreferenceManager().getSharedPreferences();
      preference.setSummary(sharedPrefs.getString(key, "Default"));
    }
  }

下面是一个基于@tdeveaux答案的PreferenceFragment内所有EditTextPreferences的工作解决方案:

public class SettingsFragment extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener {
    private static final String TAG = "SettingsFragment";

    @Override
    public void onCreate (Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.preferences);
        getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
    }

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

        for (int i = 0; i < getPreferenceScreen().getPreferenceCount(); ++i) {
            Preference preference = getPreferenceScreen().getPreference(i);
            updatePreference(preference);
        }
    }

    @Override
    public void onSharedPreferenceChanged (SharedPreferences sharedPreferences, String key) {
        updatePreference(findPreference(key));
    }

    private void updatePreference (Preference preference) {
        if (preference instanceof EditTextPreference) {
            EditTextPreference editTextPreference = (EditTextPreference)preference;
            editTextPreference.setSummary(editTextPreference.getText());
        }
    }
}

我的选择是扩展ListPreference,它是干净的:

public class ListPreferenceShowSummary extends ListPreference {

    private final static String TAG = ListPreferenceShowSummary.class.getName();

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

    public ListPreferenceShowSummary(Context context) {
        super(context);
        init();
    }

    private void init() {

        setOnPreferenceChangeListener(new OnPreferenceChangeListener() {

            @Override
            public boolean onPreferenceChange(Preference arg0, Object arg1) {
                arg0.setSummary(getEntry());
                return true;
            }
        });
    }

    @Override
    public CharSequence getSummary() {
        return super.getEntry();
    }
}

然后你添加你的settings.xml:

<yourpackage.ListPreferenceShowSummary
    android:key="key" android:title="title"
    android:entries="@array/entries" android:entryValues="@array/values"
    android:defaultValue="first value"/>

如果适合您的需求,有一些方法可以使其成为更通用的解决方案。

例如,如果你想让所有的列表首选项显示为摘要,你可以为你的onSharedPreferenceChanged实现:

public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
    Preference pref = findPreference(key);

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

这很容易扩展到其他首选项类。

通过使用PreferenceScreen和PreferenceCategory中的getPreferenceCount和getPreference功能,您可以轻松地编写一个泛型函数来遍历首选项树,设置所需类型的所有首选项的摘要到它们的toString表示

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"
 ...
 />