PreferenceFragment去完成設置頁面

大多數時候我們都是這樣去使用SharedPreferences

SharedPreferences sharedPreferences = getSharedPreferences("eric", Context.MODE_PRIVATE); //私有數據
Editor editor = sharedPreferences.edit();//獲取編輯器
editor.putString("name", "eric");
editor.putInt("age", 4);
editor.commit();//提交修改

在app設置頁面的開發中也會用到對設置項的保存,我們也會用到SharedPreferences去保存這些設置項,Android官方提供了更為簡單針對設置頁面使用SharedPreferences方法,那就是PreferenceActivity和PreferenceFragment. 下面來說下如何使用.
PreferenceActivity主要針對3.0以前的版本,PreferenceFragment則更為靈活,其實使用方法上面兩者大致一樣,所以PreferenceActivity就不展開講解,直接來看PreferenceFragment的使用
一般來說Fragment會要求去關聯一個布局的layout, 但是在PreferenceFragment則不需要這樣做,我們需要去自定義一個xml加入首選項(首選項就是配置項,官方稱為首選項). xml根節點必須是一個PreferenceScreen元素. PreferenceScreen里面的子項都作為一個獨立的控件顯示在界面里,同時還具備保存屬性.

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <CheckBoxPreference
        android:key="checkbox_preference"
        android:title="@string/title_checkbox_preference"
        android:summary="@string/summary_checkbox_preference" />
    <ListPreference
        android:key="list_preference"
        android:title="@string/title_list_preference"
        android:summary="@string/summary_list_preference"
        android:entries="@array/entries_list_preference"
        android:entryValues="@array/entryvalues_list_preference"
        android:dialogTitle="@string/dialog_title_list_preference" />
</PreferenceScreen>

顯示效果如下


image.png

以上只展示了CheckBoxPreference和ListPreference,還有其它很多Preference控件,具體可以查閱官方文檔有關Preference的字類.
如果設置項目過多,我們可以進行分類展示,有如下兩種方式可以來實現.

使用標題

加入PreferenceCategory的屬性可以進行標題的劃分.

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">

    <PreferenceCategory
        android:title="@string/inline_preferences">

        <CheckBoxPreference
            android:key="checkbox_preference"
            android:summary="@string/summary_checkbox_preference"
            android:title="@string/title_checkbox_preference"/>

    </PreferenceCategory>

    <PreferenceCategory
        android:title="@string/inline_preferences">

        <CheckBoxPreference
            android:key="checkbox_preference"
            android:summary="@string/summary_checkbox_preference"
            android:title="@string/title_checkbox_preference"/>
        <ListPreference
            android:dialogTitle="@string/dialog_title_list_preference"
            android:entries="@array/entries_list_preference"
            android:entryValues="@array/entryvalues_list_preference"
            android:key="list_preference"
            android:summary="@string/summary_list_preference"
            android:title="@string/title_list_preference"/>
    </PreferenceCategory>
</PreferenceScreen>

使用子屏幕

使用PreferenceCategory屬性可以劃分子屏幕

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">

    <PreferenceCategory
        android:title="@string/inline_preferences">

        <CheckBoxPreference
            android:key="checkbox_preference"
            android:summary="@string/summary_checkbox_preference"
            android:title="@string/title_checkbox_preference"/>

    </PreferenceCategory>

    <PreferenceScreen
        android:key="button_voicemail_category_key"
        android:title="Voice mail"
        android:persistent="false">

        <CheckBoxPreference
            android:key="checkbox_preference"
            android:summary="@string/summary_checkbox_preference"
            android:title="@string/title_checkbox_preference"/>
        <ListPreference
            android:dialogTitle="@string/dialog_title_list_preference"
            android:entries="@array/entries_list_preference"
            android:entryValues="@array/entryvalues_list_preference"
            android:key="list_preference"
            android:summary="@string/summary_list_preference"
            android:title="@string/title_list_preference"/>
    </PreferenceScreen>
</PreferenceScreen>

配置intent跳轉相應的activity

有時候我們的設置項目并不是保存一個配置項,而是去跳轉到一個新的畫面. 我們可以使用如下配置來使得首選項跳轉一個網頁

<Preference android:title="@string/prefs_web_page" >
    <intent android:action="android.intent.action.VIEW"
            android:data="http://www.example.com" />
</Preference>

當然你也可以配置顯式的intent進行跳轉,具體可以參見官方文檔.
可以設置默認值給Preference控件

<!-- default value is a boolean -->
<CheckBoxPreference
    android:defaultValue="true"
    ... />

<!-- default value is a string -->
<ListPreference
    android:defaultValue="@string/pref_syncConnectionTypes_default"
    ... />

在進入設置頁面可以調用

PreferenceManager.setDefaultValues(this, R.xml.advanced_preferences, false);

對默認值進行初始化應用, 這個接口最常用的地方就是去恢復設置.

使用首選項標頭

通常還有種需求是點擊一個首選項跳轉到另外一個屏幕,當然這個功能也可以通過PreferenceScreen來完成,但是使用PreferenceScreen不能兼容平板的情況就像下面這樣


image.png

如果要實現這種效果就要使用到hearders

<?xml version="1.0" encoding="utf-8"?>
<preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
    <header
        android:fragment="com.example.prefs.SettingsActivity$SettingsFragmentOne"
        android:title="@string/prefs_category_one"
        android:summary="@string/prefs_summ_category_one" />
    <header
        android:fragment="com.example.prefs.SettingsActivity$SettingsFragmentTwo"
        android:title="@string/prefs_category_two"
        android:summary="@string/prefs_summ_category_two" >
        <!-- key/value pairs can be included as arguments for the fragment. -->
        <extra android:name="someKey" android:value="someHeaderValue" />
    </header>
</preference-headers>

android:fragment用來標記點擊后跳轉的Fragment,extra用來傳遞參數,可以在Fragment中通過getArguments()來獲取傳遞過來的bundle數據, 這個數據最大的作用就是用來在同一個preference fragment中加載不同的preference xml.

public static class SettingsFragment extends PreferenceFragment {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        String settings = getArguments().getString("settings");
        if ("notifications".equals(settings)) {
            addPreferencesFromResource(R.xml.settings_wifi);
        } else if ("sync".equals(settings)) {
            addPreferencesFromResource(R.xml.settings_sync);
        }
    }
}

如果要顯示這個標頭文件的內容需要去重寫onBuildHeaders方法.

public class SettingsActivity extends PreferenceActivity {
    @Override
    public void onBuildHeaders(List<Header> target) {
        loadHeadersFromResource(R.xml.preference_headers, target);
    }
}

preference-headers這個標簽只能支持3.0以后的版本,如果要兼容3.0以前的版本需要另外在寫個xml作為兼容

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <Preference
        android:title="@string/prefs_category_one"
        android:summary="@string/prefs_summ_category_one"  >
        <intent
            android:targetPackage="com.example.prefs"
            android:targetClass="com.example.prefs.SettingsActivity"
            android:action="com.example.prefs.PREFS_ONE" />
    </Preference>
    <Preference
        android:title="@string/prefs_category_two"
        android:summary="@string/prefs_summ_category_two" >
        <intent
            android:targetPackage="com.example.prefs"
            android:targetClass="com.example.prefs.SettingsActivity"
            android:action="com.example.prefs.PREFS_TWO" />
    </Preference>
</PreferenceScreen>

再以如下方式加載

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ...

    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
        // Load the legacy preferences headers
        addPreferencesFromResource(R.xml.preference_headers_legacy);
    }
}

// Called only on Honeycomb and later
@Override
public void onBuildHeaders(List<Header> target) {
   loadHeadersFromResource(R.xml.preference_headers, target);
}

onBuildHeaders這個回調只會在Build.VERSION_CODES.HONEYCOMB(3.0系統)以上的版本調用。
另外我們必須要注意的一點,目前首選項不會再您調用registerOnSharedPreferenceChangeListener()時存儲對監聽器的強引用。但是,您必須存儲對監聽器的強引用,否則它將很容易被當作垃圾回收。
上面就是關于如何使用系統提供具有Preference功能的UI控件來打造一個設置界面. 更多詳細關于自定義Preference等可以參考官方文檔 https://developer.android.com/guide/topics/ui/settings

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容