如何在偏好摘要中显示Android偏好设置的当前值?
这必须经常提出。
当用户在Android应用程序中编辑首选项时,我希望他们能够在Preference
摘要中查看当前设置的首选项值。
例如:如果我有一个“丢弃旧消息”的首选项设置,指定消息需要清理的天数。 在PreferenceActivity
我希望用户看到:
“放弃旧信息” < – 标题
“ x天后清理消息” < – 摘要其中x是当前首选项值
额外的信用:使这个可重用,所以我可以很容易地适用于所有我的喜好,无论他们的types(以便它与EditTextPreference,ListPreference等与最小量的编码)。
如果适合您的需求,有办法使这个更通用的解决scheme。
例如,如果要一般性地将所有列表首选项显示为摘要,那么可以使用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
function,您可以轻松编写一个通用函数来遍历偏好树,将所需types的所有偏好摘要设置为toString
表示
这是我的解决scheme… 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 文档说可以在getSummary()
使用String格式标记:
如果汇总中包含string格式标记(即“%s”或“%1 $ s”),那么当前的input值将被replace。
在ListPreference中,只需指定android:summary="Clean up messages after %s days"
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")); } }
我的select是扩展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"/>
几个小时后,我已经花了解决这个问题,我已经实现了这个代码:
[更新:最终版本列表]
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); } }
那是我唯一的解决scheme。 在尝试从ListPreferencesinheritance并实现android:summary =“bla bla bla%s”之前。 都没有工作。
您可以覆盖默认的首选项类并实现该function。
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中,你可以使用自定义的喜好
<your.package.name.MyListPreference android:key="noteInterval" android:defaultValue="60" android:title="Notification Interval" android:entries="@array/noteInterval" android:entryValues="@array/noteIntervalValues" />
这是您需要将摘要设置为所选值的代码。 它也设置启动时的值,并尊重默认值,而不仅仅是改变。 只需将“R.layout.prefs”更改为xml文件并将setSummary方法扩展为您的需要即可。 它实际上只是处理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
也许像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() { String summary = super.getSummary().toString(); return String.format(summary, getText()); } }
并在你的xml中使用这个:
<your.package.EditTextPreference android:key="pref_alpha" android:summary="Actual value: %s" android:title="Title" android:defaultValue="default" />
所以你可以用%s
来写一个摘要而不是实际的值。
实际上, CheckBoxPreference可以根据checkbox的值指定不同的摘要。 查看android:summaryOff和android:summaryOn属性(以及相应的CheckBoxPreference方法)。
对于EditTextPreference:
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); } }
感谢您的提示!
我有一个首选项屏幕,并希望显示每个列表首选项的值作为摘要。
这是我现在的方式:
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()); } }
这适用于我,但我想知道什么是最好的解决scheme(性能,稳定性,可蚀性):Koem展示的还是这个?
如果有人仍然在寻找答案,你应该检查出三十三分之三的答案。
<ListPreference android:key="pref_list" android:title="A list of preferences" android:summary="%s" android:entries="@array/pref_list_entries" android:entryValues="@array/pref_list_entries_values" android:defaultValue="0" />
Android会用ListPreference的select器显示的首选项的当前string值replace%s。
谢谢,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)
的callback函数同样适用,
干杯,
克里斯
我用ListPreference的下列后裔解决了这个问题:
public class EnumPreference extends ListPreference { public EnumPreference(Context aContext, AttributeSet attrs) { super(aContext,attrs); } @Override protected View onCreateView(ViewGroup parent) { setSummary(getEntry()); return super.onCreateView(parent); } @Override protected boolean persistString(String aNewValue) { if (super.persistString(aNewValue)) { setSummary(getEntry()); notifyChanged(); return true; } else { return false; } } }
似乎从1.6到4.0.4都能正常工作。
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; } }
我已经看到所有投票的答案显示如何设置与当前确切的价值总结,但OP还想要的东西:
“ x天后清理消息”* < – 摘要其中x是当前首选项值
这是我的答案
正如有关ListPreference.getSummary()
文档所述 :
返回此ListPreference的摘要。 如果汇总中包含string格式标记(即“%s”或“%1 $ s”),那么当前的input值将被replace。
但是,我尝试了几个设备,似乎并没有工作。 通过一些研究,我find了一个很好的解决scheme。 它只是扩展你使用的每一个Preference
,并重写getSummary()
以使Android文档指定的工作。
如果您只想显示每个字段的纯文本值作为其摘要,则下面的代码应该是最容易维护的。 它只需要两个改变(第13行和第21行,标有“更改此处”):
package com.my.package; 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; public class PreferencesActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener { private final String[] mAutoSummaryFields = { "pref_key1", "pref_key2", "pref_key3" }; // change here private final int mEntryCount = mAutoSummaryFields.length; private Preference[] mPreferenceEntries; @SuppressWarnings("deprecation") @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.preferences_file); // change here mPreferenceEntries = new Preference[mEntryCount]; for (int i = 0; i < mEntryCount; i++) { mPreferenceEntries[i] = getPreferenceScreen().findPreference(mAutoSummaryFields[i]); } } @SuppressWarnings("deprecation") @Override protected void onResume() { super.onResume(); for (int i = 0; i < mEntryCount; i++) { updateSummary(mAutoSummaryFields[i]); // initialization } getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this); // register change listener } @SuppressWarnings("deprecation") @Override protected void onPause() { super.onPause(); getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this); // unregister change listener } private void updateSummary(String key) { for (int i = 0; i < mEntryCount; i++) { if (key.equals(mAutoSummaryFields[i])) { if (mPreferenceEntries[i] instanceof EditTextPreference) { final EditTextPreference currentPreference = (EditTextPreference) mPreferenceEntries[i]; mPreferenceEntries[i].setSummary(currentPreference.getText()); } else if (mPreferenceEntries[i] instanceof ListPreference) { final ListPreference currentPreference = (ListPreference) mPreferenceEntries[i]; mPreferenceEntries[i].setSummary(currentPreference.getEntry()); } break; } } } public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { updateSummary(key); } }
这是我的解决scheme:
构build一个首选types“getter”方法。
protected String getPreference(Preference x) { // http://stackoverflow.com/questions/3993982/how-to-check-type-of-variable-in-java if (x instanceof CheckBoxPreference) return "CheckBoxPreference"; else if (x instanceof EditTextPreference) return "EditTextPreference"; else if (x instanceof ListPreference) return "ListPreference"; else if (x instanceof MultiSelectListPreference) return "MultiSelectListPreference"; else if (x instanceof RingtonePreference) return "RingtonePreference"; else if (x instanceof SwitchPreference) return "SwitchPreference"; else if (x instanceof TwoStatePreference) return "TwoStatePreference"; else if (x instanceof DialogPreference) // Needs to be after ListPreference return "DialogPreference"; else return "undefined"; }
构build一个“setSummaryInit”方法。
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { Log.i(TAG, "+ onSharedPreferenceChanged(prefs:" + prefs + ", key:" + key + ")"); if( key != null ) { updatePreference(prefs, key); setSummary(key); } else { Log.e(TAG, "Preference without key!"); } Log.i(TAG, "- onSharedPreferenceChanged()"); } protected boolean setSummary() { return _setSummary(null); } protected boolean setSummary(String sKey) { return _setSummary(sKey); } private boolean _setSummary(String sKey) { if (sKey == null) Log.i(TAG, "Initializing"); else Log.i(TAG, sKey); // Get Preferences SharedPreferences sharedPrefs = PreferenceManager .getDefaultSharedPreferences(this); // Iterate through all Shared Preferences // http://stackoverflow.com/questions/9310479/how-to-iterate-through-all-keys-of-shared-preferences Map<String, ?> keys = sharedPrefs.getAll(); for (Map.Entry<String, ?> entry : keys.entrySet()) { String key = entry.getKey(); // Do work only if initializing (null) or updating specific preference key if ( (sKey == null) || (sKey.equals(key)) ) { String value = entry.getValue().toString(); Preference pref = findPreference(key); String preference = getPreference(pref); Log.d("map values", key + " | " + value + " | " + preference); pref.setSummary(key + " | " + value + " | " + preference); if (sKey != null) return true; } } return false; } private void updatePreference(SharedPreferences prefs, String key) { Log.i(TAG, "+ updatePreference(prefs:" + prefs + ", key:" + key + ")"); Preference pref = findPreference(key); String preferenceType = getPreference(pref); Log.i(TAG, "preferenceType = " + preferenceType); Log.i(TAG, "- updatePreference()"); }
初始化
创buildPreferenceActivity并实现OnSharedPreferenceChangeListener的公共类
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); PreferenceManager.setDefaultValues(this, R.xml.global_preferences, false); this.addPreferencesFromResource(R.xml.global_preferences); this.getPreferenceScreen().getSharedPreferences() .registerOnSharedPreferenceChangeListener(this); } protected void onResume() { super.onResume(); setSummary(); }
只是:
listPreference.setSummary("%s");
供参考:
findPreference(CharSequence key) This method was deprecated in API level 11. This function is not relevant for a modern fragment-based PreferenceActivity.
所有更多的理由来看看上面@ASD的非常光滑的Answer
( 在这里find的来源 ),说在preferences.xml
每个字段的android:summary
使用%s
。 (当前的优先值代替%s
)
<ListPreference ... android:summary="Length of longest word to return as match is %s" ... />
这里,所有这些都是从Eclipse示例SettingsActivity
中剪切掉的。 我必须复制所有这些太多的代码,以显示这些Android开发人员如何完美select更广义和稳定的编码风格。
我留下了代码以使PreferenceActivity
适应平板电脑和更大的API。
public class SettingsActivity extends PreferenceActivity { @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); setupSummaryUpdatablePreferencesScreen(); } private void setupSummaryUpdatablePreferencesScreen() { // In the simplified UI, fragments are not used at all and we instead // use the older PreferenceActivity APIs. // Add 'general' preferences. addPreferencesFromResource(R.xml.pref_general); // Bind the summaries of EditText/List/Dialog preferences to // their values. When their values change, their summaries are updated // to reflect the new value, per the Android Design guidelines. bindPreferenceSummaryToValue(findPreference("example_text")); bindPreferenceSummaryToValue(findPreference("example_list")); } /** * A preference value change listener that updates the preference's summary * to reflect its new value. */ private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() { private String TAG = SettingsActivity.class.getSimpleName(); @Override public boolean onPreferenceChange(Preference preference, Object value) { String stringValue = value.toString(); if (preference instanceof ListPreference) { // For list preferences, look up the correct display value in // the preference's 'entries' list. ListPreference listPreference = (ListPreference) preference; int index = listPreference.findIndexOfValue(stringValue); // Set the summary to reflect the new value. preference.setSummary( index >= 0 ? listPreference.getEntries()[index] : null); } else { // For all other preferences, set the summary to the value's // simple string representation. preference.setSummary(stringValue); } Log.i(TAG, "pref changed : " + preference.getKey() + " " + value); return true; } }; /** * Binds a preference's summary to its value. More specifically, when the * preference's value is changed, its summary (line of text below the * preference title) is updated to reflect the value. The summary is also * immediately updated upon calling this method. The exact display format is * dependent on the type of preference. * * @see #sBindPreferenceSummaryToValueListener */ private static void bindPreferenceSummaryToValue(Preference preference) { // Set the listener to watch for value changes. preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener); // Trigger the listener immediately with the preference's // current value. sBindPreferenceSummaryToValueListener.onPreferenceChange(preference, PreferenceManager .getDefaultSharedPreferences(preference.getContext()) .getString(preference.getKey(), "")); } }
xml/pref_general.xml
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" > <!-- NOTE: EditTextPreference accepts EditText attributes. --> <!-- NOTE: EditTextPreference's summary should be set to its value by the activity code. --> <EditTextPreference android:capitalize="words" android:defaultValue="@string/pref_default_display_name" android:inputType="textCapWords" android:key="example_text" android:maxLines="1" android:selectAllOnFocus="true" android:singleLine="true" android:title="@string/pref_title_display_name" /> <!-- NOTE: Hide buttons to simplify the UI. Users can touch outside the dialog todismiss it.--> <!-- NOTE: ListPreference's summary should be set to its value by the activity code. --> <ListPreference android:defaultValue="-1" android:entries="@array/pref_example_list_titles" android:entryValues="@array/pref_example_list_values" android:key="example_list" android:negativeButtonText="@null" android:positiveButtonText="@null" android:title="@string/pref_title_add_friends_to_messages" /> </PreferenceScreen>
values/strings_activity_settings.xml
<resources> <!-- Strings related to Settings --> <!-- Example General settings --> <string name="pref_title_display_name">Display name</string> <string name="pref_default_display_name">John Smith</string> <string name="pref_title_add_friends_to_messages">Add friends to messages</string> <string-array name="pref_example_list_titles"> <item>Always</item> <item>When possible</item> <item>Never</item> </string-array> <string-array name="pref_example_list_values"> <item>1</item> <item>0</item> <item>-1</item> </string-array> </resources>
注意:其实我只想评论一下,“Google的PreferenceActivity样本也很有趣”。 但我没有足够的声望点,所以请不要责怪我。
(对不起英文)
You have to use bindPreferenceSummaryToValue function on the onCreate method.
例:
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Add 'general' preferences, defined in the XML file addPreferencesFromResource(R.xml.pref_general); // For all preferences, attach an OnPreferenceChangeListener so the UI summary can be // updated when the preference changes. bindPreferenceSummaryToValue(findPreference(getString(R.string.pref_location_key))); bindPreferenceSummaryToValue(findPreference(getString(R.string.pref_units_key))); }
See lesson 3 on Udacity Android Course: https://www.udacity.com/course/viewer#!/c-ud853/l-1474559101/e-1643578599/m-1643578601
For EditTextPreference :
I came to this solution, of course, just if you need particular edittextpreference but you could do this with every Preference:
…………
private static final String KEY_EDIT_TEXT_PREFERENCE2 = "on_a1"; public static String value = "";
…………
private void updatePreference(Preference preference, String key) { if (key.equals(KEY_EDIT_TEXT_PREFERENCE2)) { preference = findPreference(key); if (preference instanceof EditTextPreference) { editTextPreference = (EditTextPreference) preference; editTextPreference.setSummary(editTextPreference.getText()); value = editTextPreference.getText().toString(); return; } SharedPreferences sharedPrefs = getPreferenceManager().getSharedPreferences(); preference.setSummary(sharedPrefs.getString(KEY_EDIT_TEXT_PREFERENCE2, "")); } }
Then in onResume();
@Override public void onResume() { super.onResume(); SharedPreferences etext = getPreferenceManager().getSharedPreferences(); String str = etext.getString("value", ""); editTextPreference = (EditTextPreference) findPreference(KEY_EDIT_TEXT_PREFERENCE2); editTextPreference.setText(str); editTextPreference.setSummary(editTextPreference.getText()); getPreferenceScreen().getSharedPreferences() .registerOnSharedPreferenceChangeListener(this); }
在:
@Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { updatePreference(findPreference(key), key); }
My solution is to create a custom EditTextPreference
, used in XML like this: <com.example.EditTextPreference android:title="Example 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(); } }
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.
Here is a working solution for all EditTextPreference
s inside of a PreferenceFragment
based on @tdeveaux answer:
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()); } } }
Because I'm using a custom PreferenceDataStore
, I can't add a listener to some SharedPreference
so I've had to write a somewhat hacky solution that listens to each preference:
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) }