这必须经常出现.
当用户在Android应用中编辑首选项时,我希望他们能够在Preference
摘要中查看首选项的当前设置值.
示例:如果我有"丢弃旧邮件"的"首选项"设置,该设置指定需要清除邮件的天数.在PreferenceActivity
我想让用户看到:
"丢弃旧邮件" < - 标题
" x天后清理消息" < - summary其中x是当前的Preference值
额外的功劳:使这个可重用,所以我可以轻松地将它应用到我的所有首选项,无论其类型如何(这样它可以使用EditTextPreference,ListPreference等,只需最少的编码).
如果符合您的需求,有很多方法可以使这个解决方案成为更通用的解决方案.
例如,如果您希望通常将所有列表首选项显示为摘要,则可以将其用于onSharedPreferenceChanged
实现:
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { Preference pref = findPreference(key); if (pref instanceof ListPreference) { ListPreference listPref = (ListPreference) pref; pref.setSummary(listPref.getEntry()); } }
这很容易扩展到其他偏好类.
并通过getPreferenceCount
与getPreference
在功能PreferenceScreen
和PreferenceCategory
,你可以很容易地编写一个通用函数走偏好树设置类型的所有喜好的你渴望自己的概要toString
表示
这是我的解决方案...... FWIW
package com.example.PrefTest; import android.content.SharedPreferences; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.os.Bundle; import android.preference.EditTextPreference; import android.preference.ListPreference; import android.preference.Preference; import android.preference.PreferenceActivity; import android.preference.PreferenceGroup; import android.preference.PreferenceManager; public class Preferences extends PreferenceActivity implements OnSharedPreferenceChangeListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.preferences); PreferenceManager.setDefaultValues(Preferences.this, R.xml.preferences, false); initSummary(getPreferenceScreen()); } @Override protected void onResume() { super.onResume(); // 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) { updatePrefSummary(findPreference(key)); } private void initSummary(Preference p) { if (p instanceof PreferenceGroup) { PreferenceGroup pGrp = (PreferenceGroup) p; for (int i = 0; i < pGrp.getPreferenceCount(); i++) { initSummary(pGrp.getPreference(i)); } } else { updatePrefSummary(p); } } private void updatePrefSummary(Preference p) { if (p instanceof ListPreference) { ListPreference listPref = (ListPreference) p; p.setSummary(listPref.getEntry()); } if (p instanceof EditTextPreference) { EditTextPreference editTextPref = (EditTextPreference) p; if (p.getTitle().toString().toLowerCase().contains("password")) { p.setSummary("******"); } else { p.setSummary(editTextPref.getText()); } } if (p instanceof MultiSelectListPreference) { EditTextPreference editTextPref = (EditTextPreference) p; p.setSummary(editTextPref.getText()); } } }
Android 文档说可以在以下位置使用String格式标记getSummary()
:
如果摘要中包含字符串格式标记(即"%s"或"%1 $ s"),则当前条目值将替换为其位置.
只需android:summary="Clean up messages after %s days"
在ListPreference中指定xml声明就适合我.
注意:这仅适用于ListPreference
.
如果你使用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")); } }
我的选择是扩展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:
您可以覆盖默认的Preference类并实现该功能.
public class MyListPreference extends ListPreference { public MyListPreference(Context context) { super(context); } public MyListPreference(Context context, AttributeSet attrs) { super(context, attrs); } @Override public void setValue(String value) { super.setValue(value); setSummary(getEntry()); } }
在您的xml中,您可以使用自定义首选项
几个小时后,我已经花了解决这个问题,我已经实现了这段代码:
[更新:最终版本列表]
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"之前.都没有奏效.
也许像ListPreference:修改getSummary以获得你想要的:
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()); } }
并在你的xml中使用它:
因此,您可以使用%s
而不是实际值来编写摘要.
这是将摘要设置为所选值所需的代码.它还会在启动时设置值并遵循默认值,而不仅仅是更改时.只需将"R.layout.prefs"更改为您的xml文件,并将setSummary-method扩展到您的需要.它实际上只处理ListPreferences,但它很容易自定义以尊重其他首选项.
package de.koem.timetunnel; import android.content.SharedPreferences; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.os.Bundle; import android.preference.ListPreference; import android.preference.Preference; import android.preference.PreferenceActivity; import android.preference.PreferenceGroup; public class Prefs extends PreferenceActivity implements OnSharedPreferenceChangeListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.addPreferencesFromResource(R.layout.prefs); this.initSummaries(this.getPreferenceScreen()); this.getPreferenceScreen().getSharedPreferences() .registerOnSharedPreferenceChangeListener(this); } /** * Set the summaries of all preferences */ private void initSummaries(PreferenceGroup pg) { for (int i = 0; i < pg.getPreferenceCount(); ++i) { Preference p = pg.getPreference(i); if (p instanceof PreferenceGroup) this.initSummaries((PreferenceGroup) p); // recursion else this.setSummary(p); } } /** * Set the summaries of the given preference */ private void setSummary(Preference pref) { // react on type or key if (pref instanceof ListPreference) { ListPreference listPref = (ListPreference) pref; pref.setSummary(listPref.getEntry()); } } /** * used to change the summary of a preference */ public void onSharedPreferenceChanged(SharedPreferences sp, String key) { Preference pref = findPreference(key); this.setSummary(pref); } // private static final String LOGTAG = "Prefs"; }
koem
实际上,CheckBoxPreference确实能够根据复选框值指定不同的摘要.查看android:summaryOff和android:summaryOn属性(以及相应的CheckBoxPreference方法).
public class MyEditTextPreference extends EditTextPreference { public MyEditTextPreference(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public MyEditTextPreference(Context context, AttributeSet attrs) { super(context, attrs); } @Override public void setText(String text) { super.setText(text); setSummary(text); } }
如果有人仍在寻找答案,你应该查看三十三分之一的答案.
Android将使用首选项的当前字符串值替换%s,如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 MapsharedPreferencesMap = getPreferenceScreen().getSharedPreferences().getAll(); Preference pref; ListPreference listPref; for (Map.Entry 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正在展示还是这个?
谢谢,Reto,详细解释!
如果这对任何人有任何帮助,我不得不更改Reto Meier提出的代码,以使其适用于Android版SDK 1.5
@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)
干杯,
克里斯