需求:在 PreferenceActivity / PreferenceFragment 列表中,直接顯示每個偏好設定的**目前值**(如「刪除舊訊息:7 天後」),並在使用者修改後即時更新。
讓 PreferenceActivity/Fragment 實作介面,監聽共用偏好設定變更,並在 onSharedPreferenceChanged 中更新對應 Preference 的 setSummary()。
public class SettingsFragment extends PreferenceFragmentCompat
implements SharedPreferences.OnSharedPreferenceChangeListener {
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
setPreferencesFromResource(R.xml.preferences, rootKey);
}
@Override
public void onResume() {
super.onResume();
// 1. 註冊監聽器
getPreferenceScreen().getSharedPreferences()
.registerOnSharedPreferenceChangeListener(this);
// 2. 初始化所有 Summary
updateAllSummaries();
}
@Override
public void onPause() {
super.onPause();
// 3. 取消註冊,避免洩漏
getPreferenceScreen().getSharedPreferences()
.unregisterOnSharedPreferenceChangeListener(this);
}
private void updateAllSummaries() {
SharedPreferences prefs = getPreferenceScreen().getSharedPreferences();
// 遍歷所有 Preference 更新 Summary
for (String key : prefs.getAll().keySet()) {
updateSummary(key, prefs);
}
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
// 4. 偏好設定變更時,即時更新該項 Summary
updateSummary(key, sharedPreferences);
}
private void updateSummary(String key, SharedPreferences prefs) {
Preference preference = findPreference(key);
if (preference == null) return;
// 依類型顯示不同格式
if (preference instanceof SwitchPreferenceCompat) {
boolean value = prefs.getBoolean(key, false);
preference.setSummary(value ? "已啟用" : "已停用");
} else if (preference instanceof EditTextPreference) {
String value = prefs.getString(key, "");
preference.setSummary("目前值:" + (value.isEmpty() ? "未設定" : value));
} else if (preference instanceof ListPreference) {
String value = prefs.getString(key, "");
CharSequence entry = ((ListPreference) preference).getEntry();
preference.setSummary("目前:" + (entry != null ? entry : value));
} else if (preference instanceof MultiSelectListPreference) {
Set values = prefs.getStringSet(key, Collections.emptySet());
preference.setSummary("已選 " + values.size() + " 項");
}
// 可依需求擴充其他類型
}
}
<PreferenceScreen xmlns:android="https://schemas.android.com/apk/res/android">
<SwitchPreferenceCompat
android:key="notifications_enabled"
android:title="推播通知"
android:defaultValue="true" />
<EditTextPreference
android:key="user_name"
android:title="使用者名稱"
android:dialogTitle="設定名稱" />
<ListPreference
android:key="delete_after_days"
android:title="刪除舊訊息"
android:entries="@array/delete_after_entries"
android:entryValues="@array/delete_after_values"
android:defaultValue="7" />
</PreferenceScreen>
<resources>
<string-array name="delete_after_entries">
<item>1 天後</item>
<item>3 天後</item>
<item>7 天後</item>
<item>30 天後</item>
<item>從不</item>
</string-array>
<string-array name="delete_after_values">
<item>1</item>
<item>3</item>
<item>7</item>
<item>30</item>
<item>-1</item>
</string-array>
</resources>
updateAllSummaries() 確保進入畫面即顯示正確值。PreferenceActivity / PreferenceFragment。若有大量同類型 Preference,可建立自訂類別內建 Summary 更新邏輯:
public class SummaryEditTextPreference extends EditTextPreference {
public SummaryEditTextPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) {
super.onSetInitialValue(restorePersistedValue, defaultValue);
updateSummary();
}
@Override
protected void onClick() {
super.onClick();
// 對話框確定後會自動觸發 onSharedPreferenceChanged
}
public void updateSummary() {
String value = getPersistedString("");
setSummary("目前:" + (value.isEmpty() ? "未設定" : value));
}
}
掌握此模式,能讓設定畫面資訊豐富、即時回饋,大幅提升使用者體驗。