首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android Preference 顯示目前值:OnSharedPreferenceChangeListener 實作即時更新 Summary

     編輯:程式設計綜合問答

需求:在 PreferenceActivity / PreferenceFragment 列表中,直接顯示每個偏好設定的**目前值**(如「刪除舊訊息:7 天後」),並在使用者修改後即時更新。

核心機制:實作 OnSharedPreferenceChangeListener

讓 PreferenceActivity/Fragment 實作介面,監聽共用偏好設定變更,並在 onSharedPreferenceChanged 中更新對應 Preference 的 setSummary()。

完整實作範例 (PreferenceFragmentCompat 現代寫法)


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() + " 項");
        }
        // 可依需求擴充其他類型
    }
}

XML 偏好設定範例 (res/xml/preferences.xml)

<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>

陣列資源 (res/values/arrays.xml)

<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>

關鍵點總結

  1. 在 onResume 註冊、onPause 取消註冊:生命週期綁定,避免記憶體洩漏與重複回調。
  2. 初始化時同步更新所有 Summary:updateAllSummaries() 確保進入畫面即顯示正確值。
  3. 依 Preference 具體類型格式化 Summary:Switch 顯示啟用/停用、EditText 顯示文字、ListPreference 顯示人類可讀的 entry 而非 value。
  4. 使用 PreferenceFragmentCompat (AndroidX):取代已棄用的 PreferenceActivity / PreferenceFragment。

進階:自訂 Preference 類別封裝邏輯

若有大量同類型 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));
    }
}

掌握此模式,能讓設定畫面資訊豐富、即時回饋,大幅提升使用者體驗。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved