blob: 91ac929e0fa12b8f4ae4bf27b19a9ae70d2209ea [file] [log] [blame]
page.title=設定
page.tags=偏好設定、偏好設定 Activity、偏好設定片段
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>本文件內容</h2>
<ol>
<li><a href="#Overview">總覽</a>
<ol>
<li><a href="#SettingTypes">偏好設定</a></li>
</ol>
</li>
<li><a href="#DefiningPrefs">在 XML 中定義偏好設定</a>
<ol>
<li><a href="#Groups">建立設定群組</a></li>
<li><a href="#Intents">使用意圖</a></li>
</ol>
</li>
<li><a href="#Activity">建立偏好設定 Activity</a></li>
<li><a href="#Fragment">使用偏好設定片段</a></li>
<li><a href="#Defaults">設定預設值</a></li>
<li><a href="#PreferenceHeaders">使用偏好設定標頭</a>
<ol>
<li><a href="#CreateHeaders">建立標頭檔案</a></li>
<li><a href="#DisplayHeaders">顯示標頭</a></li>
<li><a href="#BackCompatHeaders">使用偏好設定標頭支援舊版</a></li>
</ol>
</li>
<li><a href="#ReadingPrefs">讀取偏好設定</a>
<ol>
<li><a href="#Listening">接聽偏好設定變更</a></li>
</ol>
</li>
<li><a href="#NetworkUsage">管理網路使用量</a></li>
<li><a href="#Custom">建置自訂偏好設定</a>
<ol>
<li><a href="#CustomSelected">指定使用者介面</a></li>
<li><a href="#CustomSave">儲存設定值</a></li>
<li><a href="#CustomInitialize">初始化目前值</a></li>
<li><a href="#CustomDefault">提供預設值</a></li>
<li><a href="#CustomSaveState">儲存和還原偏好設定狀態</a></li>
</ol>
</li>
</ol>
<h2>重要類別</h2>
<ol>
<li>{@link android.preference.Preference}</li>
<li>{@link android.preference.PreferenceActivity}</li>
<li>{@link android.preference.PreferenceFragment}</li>
</ol>
<h2>另請參閱</h2>
<ol>
<li><a href="{@docRoot}design/patterns/settings.html">設定設計指南</a></li>
</ol>
</div>
</div>
<p>應用程式通常會包含可讓使用者修改應用程式功能和行為的設定。例如,有些應用程式可讓使用者指定是否啟用通知,或指定應用程式與雲端同步資料的頻率。
</p>
<p>如果您想要為應用程式提供設定,應該使用 Android {@link android.preference.Preference} API 建置與其他 Android 應用程式使用者體驗一致的介面 (包含系統設定)。
本文件說明如何使用 {@link android.preference.Preference} API 建置應用程式設定。
</p>
<div class="note design">
<p><strong>設定設計</strong></p>
<p>如要瞭解如何設計設定,請參閱<a href="{@docRoot}design/patterns/settings.html">設定</a>設計指南。</p>
</div>
<img src="{@docRoot}images/ui/settings/settings.png" alt="" width="435" />
<p class="img-caption"><strong>圖 1.</strong>Android 簡訊應用程式設定的螢幕擷取畫面。
選取一個 {@link android.preference.Preference} 定義的項目可以開啟介面變更設定。
</p>
<h2 id="Overview">總覽</h2>
<p>現在不使用 {@link android.view.View} 物件建置使用者介面,而是使用您在 XML 檔案中所宣告 {@link android.preference.Preference} 類別的各種子類別來建置設定。
</p>
<p>一個 {@link android.preference.Preference} 物件是單一設定的建置區塊。
每個 {@link android.preference.Preference} 都以項目的形式在清單中顯示,並為使用者提供適當的 UI 以修改設定。
例如,{@link
android.preference.CheckBoxPreference} 可以建立顯示核取方塊的清單項目,而 {@link
android.preference.ListPreference} 可以建立開啟對話方塊 (其中包含選擇清單) 的項目。</p>
<p>每個您新增的 {@link android.preference.Preference} 都會有一個對應的鍵值配對,系統可使用此鍵值對將設定儲存到您應用程式設定的預設 {@link android.content.SharedPreferences} 檔案。
當使用者變更設定,系統會為您更新 {@link android.content.SharedPreferences} 檔案中的對應值。
您唯一需要與關聯的 {@link android.content.SharedPreferences} 檔案直接互動的時候,是當您需要讀取值才能根據使用者設定判斷應用程式行為時。
</p>
<p>儲存在 {@link android.content.SharedPreferences} 的每個設定值可以是下列其中一個資料類型:
</p>
<ul>
<li>布林值</li>
<li>浮動</li>
<li>整數</li>
<li>長整數</li>
<li>字串</li>
<li>字串 {@link java.util.Set}</li>
</ul>
<p>由於您的應用程式設定 UI 是使用 {@link android.preference.Preference} 物件,而不是 {@link android.view.View} 物件建置,因此您需要使用專門的 {@link android.app.Activity} 或 {@link android.app.Fragment} 子類別來顯示清單設定:
</p>
<ul>
<li>如果應用程式支援的 Android 版本早於 3.0 (API 級別 10 及較早版本),您必須以 {@link android.preference.PreferenceActivity} 類別延伸的形式建置 Activity。
</li>
<li>在 Android 3.0 及更新版本上,您應該使用傳統 {@link android.app.Activity},它託管了顯示應用程式設定的 {@link android.preference.PreferenceFragment}。
然而,當您有多個設定群組時,還可以使用 {@link android.preference.PreferenceActivity} 在大螢幕建立兩個面板的版面配置。
</li>
</ul>
<p>如何設定 {@link android.preference.PreferenceActivity} 和 {@link
android.preference.PreferenceFragment} 執行個體在<a href="#Activity">建立偏好設定 Activity</a> 和<a href="#Fragment">使用偏好設定片段</a>小節中有相關說明。
</p>
<h3 id="SettingTypes">偏好設定</h3>
<p>應用程式的每個設定都會以 {@link
android.preference.Preference} 類別的特定子類別代表。每個子類別包含一組核心屬性,可讓您為設定指定標題等項目和預設值。
每個子類別還提供自己專屬的屬性和使用者介面。
例如,圖 1 顯示簡訊應用程式設定的螢幕擷取畫面。
設定畫面中的每個清單項目都由不同的 {@link
android.preference.Preference} 物件支援。</p>
<p>下列為幾個最常見的偏好設定:</p>
<dl>
<dt>{@link android.preference.CheckBoxPreference}</dt>
<dd>為啟用或停用的設定顯示含有核取方塊的項目。儲存的值是布林值 (如果選取 <code>true</code>)。
</dd>
<dt>{@link android.preference.ListPreference}</dt>
<dd>開啟含有選項按鈕清單的對話方塊。儲存的值可以是任何支援的值類型 (如上所列)。
</dd>
<dt>{@link android.preference.EditTextPreference}</dt>
<dd>開啟含有 {@link android.widget.EditText} 小工具的對話方塊。儲存的值是 {@link
java.lang.String}。</dd>
</dl>
<p>請參閱 {@link android.preference.Preference} 類別,以取得所有其他子類別及其對應屬性的清單。
</p>
<p>當然,內建類別無法滿足所有需要,您的應用程式可能需要更專門的功能。
例如,平台目前無法提供 {@link
android.preference.Preference} 類別以選取數字或日期。因此,您可能需要定義自己的 {@link android.preference.Preference} 子類別。
如需執行此操作的協助,請參閱<a href="#Custom">建置自訂偏好設定</a>。</p>
<h2 id="DefiningPrefs">在 XML 中定義偏好設定</h2>
<p>雖然您可以在執行階段將新的 {@link android.preference.Preference} 物件具現化,但您仍應該在 XML 中定義設定清單,並在其中包含 {@link android.preference.Preference} 物件的階層。
使用 XML 檔案定義設定集合是較建議的做法,因為該檔案提供的易讀結構很容易更新。
而且,雖然您仍然可以在執行階段修改集合,但您的應用程式設定通常是預先定義好的。
</p>
<p>每個 {@link android.preference.Preference} 子類別都可透過與類別名稱相符的 XML 元素進行宣告,例如 {@code &lt;CheckBoxPreference&gt;}。
</p>
<p>您必須將 XML 檔案儲存在 {@code res/xml/} 目錄中。雖然您可以自由命名檔案,但在傳統上會命名為 {@code preferences.xml}。
您通常只需要一個檔案,因為階層 (會開啟自己的設定清單) 中的子目錄是透過 {@link android.preference.PreferenceScreen} 的巢狀執行個體進行宣告。
</p>
<p class="note"><strong>注意:</strong>如果您想要為設定建立多個面板的版面配置,則您需要為每個片段準備個別的 XML 檔案。
</p>
<p>XML 檔案的根節點必須是 {@link android.preference.PreferenceScreen
&lt;PreferenceScreen&gt;} 元素。您要將每個 {@link
android.preference.Preference} 新增到此元素內。您在 {@link android.preference.PreferenceScreen &lt;PreferenceScreen&gt;} 元素內新增的每個子項會在設定清單中顯示為單一項目。
</p>
<p>例如:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
&lt;CheckBoxPreference
android:key="pref_sync"
android:title="@string/pref_sync"
android:summary="@string/pref_sync_summ"
android:defaultValue="true" />
&lt;ListPreference
android:dependency="pref_sync"
android:key="pref_syncConnectionType"
android:title="@string/pref_syncConnectionType"
android:dialogTitle="@string/pref_syncConnectionType"
android:entries="@array/pref_syncConnectionTypes_entries"
android:entryValues="@array/pref_syncConnectionTypes_values"
android:defaultValue="@string/pref_syncConnectionTypes_default" />
&lt;/PreferenceScreen>
</pre>
<p>此範例中有一個 {@link android.preference.CheckBoxPreference} 和一個 {@link
android.preference.ListPreference}。這兩個項目都包含下列三個屬性:</p>
<dl>
<dt>{@code android:key}</dt>
<dd>需要這個屬性才能保留資料值的偏好設定。它會指定當系統將此設定值儲存於 {@link
android.content.SharedPreferences} 時要使用的唯一索引鍵 (字串)。
<p>只有在下列情況下不需要此屬性:<em></em>偏好設定為 {@link android.preference.PreferenceCategory} 或 {@link android.preference.PreferenceScreen},或者偏好設定指定 {@link android.content.Intent} 進行呼叫 (搭配 <a href="#Intents">{@code &lt;intent&gt;}</a> 元素) 或 {@link android.app.Fragment} 進行顯示 (搭配 <a href="{@docRoot}reference/android/preference/Preference.html#attr_android:fragment">{@code
android:fragment}</a> 屬性)。
</p>
</dd>
<dt>{@code android:title}</dt>
<dd>這可為設定提供使用者可見的名稱。</dd>
<dt>{@code android:defaultValue}</dt>
<dd>這可指定系統在 {@link
android.content.SharedPreferences} 檔案中應設定的初始值。您應該為所有設定提供預設值。
</dd>
</dl>
<p>如需所有其他支援的屬性相關資訊,請參閱 {@link
android.preference.Preference} (及個別子類別) 文件。</p>
<div class="figure" style="width:300px">
<img src="{@docRoot}images/ui/settings/settings-titles.png" alt="" />
<p class="img-caption"><strong>圖 2.</strong>設定含有標題的類別。
<br/><b>1.</b>類別以 {@link
android.preference.PreferenceCategory &lt;PreferenceCategory&gt;} 元素指定。 <br/><b>2.</b>標題以 {@code android:title} 屬性指定。
</p>
</div>
<p>如果您的設定清單超過約 10 個項目,您可以新增標題來定義設定群組,或在分開的畫面顯示這些群組。
這些選項在下列幾節有詳細的描述。</p>
<h3 id="Groups">建立設定群組</h3>
<p>如果您的清單有 10 個以上的項目,掃描、理解和處理這些項目對使用者而言可能會很困難。
如要解決這個問題,可將部分或所有設定分成不同的群組,有效地將一長串清單分成多個簡短的清單。
一組包含相關設定的群組可以下列其中一種方式顯示:</p>
<ul>
<li><a href="#Titles">使用標題</a></li>
<li><a href="#Subscreens">使用子畫面</a></li>
</ul>
<p>您可以使用上述一種或兩種分組技巧來整理您的應用程式設定。決定要使用哪種方法或如何分割設定時,您應該要依照 Android 設計<a href="{@docRoot}design/patterns/settings.html">設定</a>指南中的指導方針進行。
</p>
<h4 id="Titles">使用標題</h4>
<p>如果您想要在設定群組間使用標題區分 (如圖 2 所示),將 {@link android.preference.Preference} 物件的每個群組放入 {@link
android.preference.PreferenceCategory}。
</p>
<p>例如:</p>
<pre>
&lt;PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
&lt;PreferenceCategory
android:title="&#64;string/pref_sms_storage_title"
android:key="pref_key_storage_settings">
&lt;CheckBoxPreference
android:key="pref_key_auto_delete"
android:summary="&#64;string/pref_summary_auto_delete"
android:title="&#64;string/pref_title_auto_delete"
android:defaultValue="false"... />
&lt;Preference
android:key="pref_key_sms_delete_limit"
android:dependency="pref_key_auto_delete"
android:summary="&#64;string/pref_summary_delete_limit"
android:title="&#64;string/pref_title_sms_delete"... />
&lt;Preference
android:key="pref_key_mms_delete_limit"
android:dependency="pref_key_auto_delete"
android:summary="&#64;string/pref_summary_delete_limit"
android:title="&#64;string/pref_title_mms_delete" ... />
&lt;/PreferenceCategory>
...
&lt;/PreferenceScreen>
</pre>
<h4 id="Subscreens">使用子畫面</h4>
<p>如果您想將設定群組放入子畫面 (如圖 3 所示),將 {@link android.preference.Preference} 物件的群組放入 {@link
android.preference.PreferenceScreen}。
</p>
<img src="{@docRoot}images/ui/settings/settings-subscreen.png" alt="" />
<p class="img-caption"><strong>圖 3.</strong>設定子畫面。{@code
&lt;PreferenceScreen&gt;} 元素建立的項目會在選取時開啟獨立的清單以顯示巢狀設定。
</p>
<p>例如:</p>
<pre>
&lt;PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
&lt;!-- opens a subscreen of settings -->
&lt;PreferenceScreen
android:key="button_voicemail_category_key"
android:title="&#64;string/voicemail"
android:persistent="false">
&lt;ListPreference
android:key="button_voicemail_provider_key"
android:title="&#64;string/voicemail_provider" ... />
&lt;!-- opens another nested subscreen -->
&lt;PreferenceScreen
android:key="button_voicemail_setting_key"
android:title="&#64;string/voicemail_settings"
android:persistent="false">
...
&lt;/PreferenceScreen>
&lt;RingtonePreference
android:key="button_voicemail_ringtone_key"
android:title="&#64;string/voicemail_ringtone_title"
android:ringtoneType="notification" ... />
...
&lt;/PreferenceScreen>
...
&lt;/PreferenceScreen>
</pre>
<h3 id="Intents">使用意圖</h3>
<p>在某些情況下,您可能會希望偏好設定項目開啟不同的 Activity 而不是設定畫面,例如,開啟網路瀏覽器以檢視網頁。
如要在使用者選取偏好設定項目時呼叫 {@link
android.content.Intent},請新增 {@code &lt;intent&gt;} 元素做為對應 {@code &lt;Preference&gt;} 元素的子項。
</p>
<p>例如,您可以使用下列方法透過偏好設定項目開啟網頁:</p>
<pre>
&lt;Preference android:title="@string/prefs_web_page" >
&lt;intent android:action="android.intent.action.VIEW"
android:data="http://www.example.com" />
&lt;/Preference>
</pre>
<p>您可以使用下列屬性建立隱含和明確意圖:</p>
<dl>
<dt>{@code android:action}</dt>
<dd>根據 {@link android.content.Intent#setAction setAction()} 方法指派的動作。
</dd>
<dt>{@code android:data}</dt>
<dd>根據 {@link android.content.Intent#setData setData()} 方法指派的資料。</dd>
<dt>{@code android:mimeType}</dt>
<dd>根據 {@link android.content.Intent#setType setType()} 方法指派的 MIME 類型。
</dd>
<dt>{@code android:targetClass}</dt>
<dd>根據 {@link android.content.Intent#setComponent
setComponent()} 方法指派的元件名稱類別部分。</dd>
<dt>{@code android:targetPackage}</dt>
<dd>根據 {@link
android.content.Intent#setComponent setComponent()} 方法指派的元件名稱封裝部分。</dd>
</dl>
<h2 id="Activity">建立偏好設定 Activity</h2>
<p>如要在 Activity 中顯示設定,延伸 {@link
android.preference.PreferenceActivity} 類別。這是傳統 {@link
android.app.Activity} 類別的延伸,可根據 {@link
android.preference.Preference} 物件的階層顯示設定清單。當使用者進行變更時,{@link android.preference.PreferenceActivity} 會自動保留與每個 {@link
android.preference.Preference} 關聯的設定。
</p>
<p class="note"><strong>注意:</strong>如果您針對 Android 3.0 及更新版本開發應用程式,您應該改為使用 {@link android.preference.PreferenceFragment}。
前往下一個<a href="#Fragment">使用偏好設定片段</a>章節。
</p>
<p>最需要注意的一件事就是,不要在 {@link
android.preference.PreferenceActivity#onCreate onCreate()} 呼叫期間載入檢視的版面配置。您應該要呼叫 {@link
android.preference.PreferenceActivity#addPreferencesFromResource addPreferencesFromResource()},將您在 XML 檔案中宣告的偏好設定新增到 Activity 中。
例如,下列為功能 {@link android.preference.PreferenceActivity} 所需的基本程式碼:
</p>
<pre>
public class SettingsActivity extends PreferenceActivity {
&#64;Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
}
</pre>
<p>事實上,這個程式碼對某些應用程式而言已經足夠,因為使用者修改偏好設定後,系統會將變更儲存到預設 {@link android.content.SharedPreferences} 檔案,當您需要檢查使用者設定時,您的其他應用程式元件就能進行讀取。
但是,許多應用程式需要更多一點程式碼,以接聽對偏好設定進行的變更。
如需在 {@link android.content.SharedPreferences} 檔案接聽變更的相關資訊,請參閱<a href="#ReadingPrefs">讀取偏好設定</a>。
</p>
<h2 id="Fragment">使用偏好設定片段</h2>
<p>如果您針對 Android 3.0 (API 級別 11) 及更新版本進行開發,您應該使用 {@link
android.preference.PreferenceFragment} 顯示 {@link android.preference.Preference} 物件清單。
您可以將 {@link android.preference.PreferenceFragment} 新增到任何 Activity &mdash; 您不需要使用 {@link android.preference.PreferenceActivity}。
</p>
<p><a href="{@docRoot}guide/components/fragments.html">片段</a>單就 Activity 而言,可為您的應用程式提供更有彈性的架構,無論您建置哪一種 Activity 都一樣。
因此,我們建議您盡可能使用 {@link
android.preference.PreferenceFragment} 來控制設定的顯示,而不要使用 {@link
android.preference.PreferenceActivity}。</p>
<p>實作 {@link android.preference.PreferenceFragment} 可以很簡單,只要定義 {@link android.preference.PreferenceFragment#onCreate onCreate()} 方法,透過 {@link android.preference.PreferenceFragment#addPreferencesFromResource
addPreferencesFromResource()} 載入偏好設定檔案。
例如:</p>
<pre>
public static class SettingsFragment extends PreferenceFragment {
&#64;Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.preferences);
}
...
}
</pre>
<p>之後,您可以將此片段新增至 {@link android.app.Activity},做法與任何其他
{@link android.app.Fragment} 一樣。例如:</p>
<pre>
public class SettingsActivity extends Activity {
&#64;Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Display the fragment as the main content.
getFragmentManager().beginTransaction()
.replace(android.R.id.content, new SettingsFragment())
.commit();
}
}
</pre>
<p class="note"><strong>注意:</strong>{@link android.preference.PreferenceFragment} 沒有自己的 {@link android.content.Context} 物件。
如果您需要 {@link android.content.Context} 物件,可以呼叫 {@link android.app.Fragment#getActivity()}。
不過,必須小心,只能在片段附加到 Activity 時才能呼叫 {@link android.app.Fragment#getActivity()}。
如果未附加片段,或是在生命週期期間中斷連結,{@link
android.app.Fragment#getActivity()} 將傳回 null。
</p>
<h2 id="Defaults">設定預設值</h2>
<p>您建立的偏好設定可能為應用程式定義了一些重要的行為,因此當使用者第一次開啟您的應用程式時,務必使用每個 {@link android.preference.Preference} 預設值來初始化關聯的 {@link android.content.SharedPreferences} 檔案。
</p>
<p>您必須要做的第一件事,就是使用 {@code android:defaultValue} 屬性指定 XML 檔案中每個 {@link
android.preference.Preference} 物件的預設值。
值可以是適用於對應 {@link android.preference.Preference} 物件的任何資料類型。
例如:
</p>
<pre>
&lt;!-- default value is a boolean -->
&lt;CheckBoxPreference
android:defaultValue="true"
... />
&lt;!-- default value is a string -->
&lt;ListPreference
android:defaultValue="@string/pref_syncConnectionTypes_default"
... />
</pre>
<p>之後,從您應用程式主 Activity &mdash; 以及使用者第一次進入您應用程式所使用的任何其他 Activity &mdash; 的 {@link android.app.Activity#onCreate onCreate()} 方法呼叫 {@link android.preference.PreferenceManager#setDefaultValues
setDefaultValues()}:
</p>
<pre>
PreferenceManager.setDefaultValues(this, R.xml.advanced_preferences, false);
</pre>
<p>在 {@link android.app.Activity#onCreate onCreate()} 期間呼叫它,可確保您的應用程式正確地以預設值初始化,您的應用程式可能需要讀取這些預設值,才能判斷一些行為 (例如,使用行動網路時是否可下載資料)。
</p>
<p>這個方法採用三種引數:</p>
<ul>
<li>您的應用程式 {@link android.content.Context}。</li>
<li>您要設定預設值之偏好設定 XML 檔案的資源 ID。</li>
<li>布林值指出預設值是否要設定一次以上。
<p>如果為 <code>false</code>,系統只會在過去從未呼叫此方法時設定預設值 (或者預設值共用偏好設定檔案的 {@link android.preference.PreferenceManager#KEY_HAS_SET_DEFAULT_VALUES} 為 false)。
</p></li>
</ul>
<p>只要將第三個引數設為 <code>false</code>,您可以在每次 Activity 啟動時很安全地呼叫此方法,而不會將使用者儲存的偏好設定重設為預設值。
不過,如果您將它設為 <code>true</code>,會將任何之前的值覆寫為預設值。
</p>
<h2 id="PreferenceHeaders">使用偏好設定標頭</h2>
<p>在少數情況下,您可能會想將設定設計為只在第一個畫面顯示<a href="#Subscreens">子畫面</a>清單(與系統設定應用程式一樣,如圖 4 和 5 所示)。
當您為 Android 3.0 及更新版本開發這類設計時,您應該使用 Android 3.0 的新「標頭」功能,而不是使用巢狀 {@link android.preference.PreferenceScreen} 元素建置子畫面。
</p>
<p>如要使用標頭建置設定,您必須:</p>
<ol>
<li>將每個設定群組分成不同的 {@link
android.preference.PreferenceFragment} 執行個體。也就是說,每個設定群組需要一個獨立的 XML 檔案。
</li>
<li>建立一個 XML 標頭檔案,其中列出每個設定群組以及宣告哪些片段包含對應的設定清單。
</li>
<li>延伸 {@link android.preference.PreferenceActivity} 類別以託管您的設定。</li>
<li>實作 {@link
android.preference.PreferenceActivity#onBuildHeaders onBuildHeaders()} 回呼以指定標頭檔案。
</li>
</ol>
<p>使用這個設計最大的好處在於在大螢幕執行時,
{@link android.preference.PreferenceActivity} 會自動顯示兩個面板的版面配置,如圖 4 所示。</p>
<p>即使應用程式支援的 Android 版本較 3.0 舊,您還是可以建置應用程式在新版的裝置上使用 {@link android.preference.PreferenceFragment} 顯示兩個面板,同時仍然支援舊版裝置上的傳統多畫面階層 (請參閱<a href="#BackCompatHeaders">使用偏好設定標頭支援舊版</a>)。
</p>
<img src="{@docRoot}images/ui/settings/settings-headers-tablet.png" alt="" />
<p class="img-caption"><strong>圖 4.</strong>含標頭的兩個面板版面配置。 <br/><b>1.</b>標頭以 XML 標頭檔案定義。
<br/><b>2.</b>每個設定群組是由標頭檔案 {@code &lt;header&gt;} 元素指定的{@link android.preference.PreferenceFragment} 所定義。
</p>
<img src="{@docRoot}images/ui/settings/settings-headers-handset.png" alt="" />
<p class="img-caption"><strong>圖 5.</strong>含設定標頭的手機裝置。選取項目後,關聯的 {@link android.preference.PreferenceFragment} 會取代標頭。
</p>
<h3 id="CreateHeaders" style="clear:left">建立標頭檔案</h3>
<p>您標頭清單中的每個設定群組是由根 {@code &lt;preference-headers&gt;} 元素中的單一 {@code &lt;header&gt;} 元素指定。
例如:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
&lt;header
android:fragment="com.example.prefs.SettingsActivity$SettingsFragmentOne"
android:title="@string/prefs_category_one"
android:summary="@string/prefs_summ_category_one" />
&lt;header
android:fragment="com.example.prefs.SettingsActivity$SettingsFragmentTwo"
android:title="@string/prefs_category_two"
android:summary="@string/prefs_summ_category_two" >
&lt;!-- key/value pairs can be included as arguments for the fragment. -->
&lt;extra android:name="someKey" android:value="someHeaderValue" />
&lt;/header>
&lt;/preference-headers>
</pre>
<p>有了 {@code android:fragment} 屬性,每個標頭會宣告當使用者選取標頭時,應該開啟的 {@link
android.preference.PreferenceFragment} 執行個體。</p>
<p>{@code &lt;extras&gt;} 元素可讓您將鍵值配對傳送到 {@link
android.os.Bundle} 中的片段。片段可以透過呼叫 {@link
android.app.Fragment#getArguments()} 擷取引數。您可以因各種理由將引數傳送到片段,但其中一個最好的理由是針對每個群組重複使用 {@link
android.preference.PreferenceFragment} 中相同的子類別,並使用引數指定應載入片段的偏好設定 XML 檔案。
</p>
<p>例如,當每個標頭使用 {@code "settings"} 索引鍵定義 {@code &lt;extra&gt;} 引數時,下列片段可在多個設定群組重複使用:
</p>
<pre>
public static class SettingsFragment extends PreferenceFragment {
&#64;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);
}
}
}
</pre>
<h3 id="DisplayHeaders">顯示標頭</h3>
<p>如要顯示偏好設定標頭,必須實作 {@link
android.preference.PreferenceActivity#onBuildHeaders onBuildHeaders()} 回呼方法,並呼叫 {@link android.preference.PreferenceActivity#loadHeadersFromResource
loadHeadersFromResource()}。
例如:</p>
<pre>
public class SettingsActivity extends PreferenceActivity {
&#64;Override
public void onBuildHeaders(List&lt;Header> target) {
loadHeadersFromResource(R.xml.preference_headers, target);
}
}
</pre>
<p>當使用者從標頭清單選取項目時,系統會開啟關聯的 {@link
android.preference.PreferenceFragment}。</p>
<p class="note"><strong>注意:</strong>使用偏好設定標頭時,{@link
android.preference.PreferenceActivity} 的子類別不需要實作 {@link
android.preference.PreferenceActivity#onCreate onCreate()} 方法,這是因為 Activity 唯一需要做的工作就是載入標頭。
</p>
<h3 id="BackCompatHeaders">使用偏好設定標頭支援舊版</h3>
<p>如果您應用程式支援的 Android 版本比 3.0 舊,您仍然可以在 Android 3.0 及更新版本執行時,使用標頭提供兩個面板的版面配置。
您只需要建立一個額外的偏好設定 XML 檔案,該檔案要使用行為與標頭項目 (供舊版 Android 使用) 一樣的基本 {@link android.preference.Preference
&lt;Preference&gt;} 元素。
</p>
<p>但是,不會開啟新的 {@link android.preference.PreferenceScreen},每個 {@link
android.preference.Preference &lt;Preference&gt;} 元素會傳送一個 {@link android.content.Intent} 到 {@link android.preference.PreferenceActivity},以指定要載入的偏好設定 XML 檔案。
</p>
<p>例如,下列為使用 Android 3.0及更新版本的偏好設定標頭 XML 檔案 ({@code res/xml/preference_headers.xml}):
</p>
<pre>
&lt;preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
&lt;header
android:fragment="com.example.prefs.SettingsFragmentOne"
android:title="@string/prefs_category_one"
android:summary="@string/prefs_summ_category_one" />
&lt;header
android:fragment="com.example.prefs.SettingsFragmentTwo"
android:title="@string/prefs_category_two"
android:summary="@string/prefs_summ_category_two" />
&lt;/preference-headers>
</pre>
<p>而,這裡有個偏好設定檔案為 Android 3.0 以下版本提供相同的標頭 ({@code res/xml/preference_headers_legacy.xml}):
</p>
<pre>
&lt;PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
&lt;Preference
android:title="@string/prefs_category_one"
android:summary="@string/prefs_summ_category_one" >
&lt;intent
android:targetPackage="com.example.prefs"
android:targetClass="com.example.prefs.SettingsActivity"
android:action="com.example.prefs.PREFS_ONE" />
&lt;/Preference>
&lt;Preference
android:title="@string/prefs_category_two"
android:summary="@string/prefs_summ_category_two" >
&lt;intent
android:targetPackage="com.example.prefs"
android:targetClass="com.example.prefs.SettingsActivity"
android:action="com.example.prefs.PREFS_TWO" />
&lt;/Preference>
&lt;/PreferenceScreen>
</pre>
<p>因為 Android 3.0 已加入對 {@code &lt;preference-headers&gt;} 的支援,系統只會在 Androd 3.0 或更新版本執行時,才會呼叫 {@link
android.preference.PreferenceActivity} 中的 {@link android.preference.PreferenceActivity#onBuildHeaders onBuildHeaders()}。
如要載入「舊版」標頭檔案 ({@code preference_headers_legacy.xml}),您必須檢查 Android 版本,如果版本比 Android 3.0 更舊 ({@link
android.os.Build.VERSION_CODES#HONEYCOMB}),呼叫 {@link
android.preference.PreferenceActivity#addPreferencesFromResource addPreferencesFromResource()} 以載入舊版標頭檔案。
例如:</p>
<pre>
&#64;Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
if (Build.VERSION.SDK_INT &lt; Build.VERSION_CODES.HONEYCOMB) {
// Load the legacy preferences headers
addPreferencesFromResource(R.xml.preference_headers_legacy);
}
}
// Called only on Honeycomb and later
&#64;Override
public void onBuildHeaders(List&lt;Header> target) {
loadHeadersFromResource(R.xml.preference_headers, target);
}
</pre>
<p>最後一件要做的事,是處理傳送到 Activity 的 {@link android.content.Intent},以識別要載入的偏好設定檔案。
擷取意圖的動作,並將它與偏好設定 XML {@code &lt;intent&gt;} 標籤中使用的已知動作字串進行比對:
</p>
<pre>
final static String ACTION_PREFS_ONE = "com.example.prefs.PREFS_ONE";
...
&#64;Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String action = getIntent().getAction();
if (action != null &amp;&amp; action.equals(ACTION_PREFS_ONE)) {
addPreferencesFromResource(R.xml.preferences);
}
...
else if (Build.VERSION.SDK_INT &lt; Build.VERSION_CODES.HONEYCOMB) {
// Load the legacy preferences headers
addPreferencesFromResource(R.xml.preference_headers_legacy);
}
}
</pre>
<p>請注意,{@link
android.preference.PreferenceActivity#addPreferencesFromResource addPreferencesFromResource()} 的連續呼叫會將所有偏好設定堆疊在單一清單中,因此請確定將條件鏈結到 else-if 陳述式時只會呼叫它一次。
</p>
<h2 id="ReadingPrefs">讀取偏好設定</h2>
<p>根據預設,透過呼叫靜態方法 {@link
android.preference.PreferenceManager#getDefaultSharedPreferences
PreferenceManager.getDefaultSharedPreferences()},您應用程式中的所有偏好設定會儲存可從應用程式內任何地方存取的檔案中。
這會傳回 {@link
android.content.SharedPreferences} 物件,其中包含與您 {@link
android.preference.PreferenceActivity} 使用之 {@link android.preference.Preference} 物件關聯的所有鍵值配對。
</p>
<p>例如,下列說明如何從應用程式中的任何其他 Activity 讀取其中一個偏好設定值:
</p>
<pre>
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
String syncConnPref = sharedPref.getString(SettingsActivity.KEY_PREF_SYNC_CONN, "");
</pre>
<h3 id="Listening">接聽偏好設定變更</h3>
<p>使用者變更其中一個偏好設定後,您想要立即收到通知的原因有好幾個。
如要在任何偏好設定發生變更時收到回呼,實作 {@link android.content.SharedPreferences.OnSharedPreferenceChangeListener
SharedPreference.OnSharedPreferenceChangeListener} 介面,並呼叫 {@link
android.content.SharedPreferences#registerOnSharedPreferenceChangeListener
registerOnSharedPreferenceChangeListener()} 為 {@link android.content.SharedPreferences} 物件註冊接聽器。
</p>
<p>介面只有一個回呼方式 {@link
android.content.SharedPreferences.OnSharedPreferenceChangeListener#onSharedPreferenceChanged
onSharedPreferenceChanged()},而且在 Activity 中實作介面可能對您來說會更為容易。
例如:</p>
<pre>
public class SettingsActivity extends PreferenceActivity
implements OnSharedPreferenceChangeListener {
public static final String KEY_PREF_SYNC_CONN = "pref_syncConnectionType";
...
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) {
if (key.equals(KEY_PREF_SYNC_CONN)) {
Preference connectionPref = findPreference(key);
// Set summary to be the user-description for the selected value
connectionPref.setSummary(sharedPreferences.getString(key, ""));
}
}
}
</pre>
<p>在此範例中,方法會檢查是否是針對已知的偏好設定索引鍵設定進行變更。它會呼叫 {@link android.preference.PreferenceActivity#findPreference findPreference()} 以取得變更的 {@link android.preference.Preference} 物件,以便將項目摘要修改為使用者選取的描述。
也就是說,當設定為 {@link
android.preference.ListPreference} 或其他多選擇設定時,如果設定變更為顯示目前狀態 (如圖 5 顯示的休眠設定),您應該呼叫 {@link
android.preference.Preference#setSummary setSummary()}。
</p>
<p class="note"><strong>注意:</strong>如 Android 設計文件中有關<a href="{@docRoot}design/patterns/settings.html">設定</a>的說明所述,我們建議您在每次使用者變更偏好設定時更新 {@link android.preference.ListPreference} 的摘要,以描述目前的設定。
</p>
<p>為了在 Activity 中正確管理生命週期,我們建議您分別在 {@link
android.app.Activity#onResume} 和 {@link android.app.Activity#onPause} 回呼期間,註冊和解決註冊您的 {@link android.content.SharedPreferences.OnSharedPreferenceChangeListener}:
</p>
<pre>
&#64;Override
protected void onResume() {
super.onResume();
getPreferenceScreen().getSharedPreferences()
.registerOnSharedPreferenceChangeListener(this);
}
&#64;Override
protected void onPause() {
super.onPause();
getPreferenceScreen().getSharedPreferences()
.unregisterOnSharedPreferenceChangeListener(this);
}
</pre>
<p class="caution"><strong>注意:</strong>當您呼叫 {@link
android.content.SharedPreferences#registerOnSharedPreferenceChangeListener
registerOnSharedPreferenceChangeListener()} 時,偏好設定管理員目前不會在接聽器儲存強式參照。
您必須將強式參照儲存到接聽器,否則它會很容易受記憶體回收的影響。
我們建議您在物件的執行個體資料中保留接聽器參照,如此一來您可以在需要接聽器時隨時使用。
</p>
<p>例如,在下列程式碼中,呼叫器沒有保留接聽器參照。
因此,接聽器將受到記憶體回收的支配,而且會在未來不明確的時間發生失敗:
</p>
<pre>
prefs.registerOnSharedPreferenceChangeListener(
// Bad! The listener is subject to garbage collection!
new SharedPreferences.OnSharedPreferenceChangeListener() {
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
// listener implementation
}
});
</pre>
<p>將接聽器參照儲存在物件的執行個體資料欄位中,可以在需要接聽器時隨時使用:
</p>
<pre>
SharedPreferences.OnSharedPreferenceChangeListener listener =
new SharedPreferences.OnSharedPreferenceChangeListener() {
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
// listener implementation
}
};
prefs.registerOnSharedPreferenceChangeListener(listener);
</pre>
<h2 id="NetworkUsage">管理網路使用量</h2>
<p>從 Android 4.0 開始,系統的設定應用程式允許使用者查看應用程式在前景和背景時使用了多少網路資料。
然後,使用者可以停用個別應用程式的背景資料。
如要避免使用者停用您的應用程式從背景存取資料,您應該有效率地使用資料連線,並允許使用者透過應用程式設定精簡您的應用程式資料使用量。
<p>
<p>例如,您可以讓使用者控制同步資料的頻率,無論您的應用程式只在 Wi-Fi 上執行上傳/下載、應用程式在漫遊使用資料等。
使用者有了這些控制項,就比較不會在快要達到在系統設定中設定的限制時停用您應用程式的資料存取,因為他們可以準確地控制您應用程式使用的資料量。
</p>
<p>您在 {@link android.preference.PreferenceActivity} 新增所需的偏好設定以控制應用程式的資料習慣後,您應該在宣示說明檔新增 {@link
android.content.Intent#ACTION_MANAGE_NETWORK_USAGE} 的意圖篩選器。
例如:</p>
<pre>
&lt;activity android:name="SettingsActivity" ... >
&lt;intent-filter>
&lt;action android:name="android.intent.action.MANAGE_NETWORK_USAGE" />
&lt;category android:name="android.intent.category.DEFAULT" />
&lt;/intent-filter>
&lt;/activity>
</pre>
<p>這個意圖篩選器向系統指出,是 Activity 在控制您的應用程式資料使用量。
因此,當使用者從系統設定應用程式檢查您的應用程式使用了多少資料量時,可以使用 [檢視應用程式設定] 按鈕啟動您的<em></em> {@link android.preference.PreferenceActivity},讓使用者精簡您應用程式使用的資料量。
</p>
<h2 id="Custom">建置自訂偏好設定</h2>
<p>Android 架構包含各式各樣的 {@link android.preference.Preference} 子類別,可讓您建置所種不同設定類型的 UI。不過,您可能會發現內建解決方案中可能沒有您所需的設定,例如數字挑選器或日期挑選器。
在這類情況下,您需要延伸 {@link android.preference.Preference} 類別或其中一個其他子類別,以建立自訂的偏好設定。
</p>
<p>當您延伸 {@link android.preference.Preference} 類別時,需要執行幾個重要工作:
</p>
<ul>
<li>指定使用者選取設定時要顯示的使用者介面。</li>
<li>視需要儲存設定值。</li>
<li>顯示 {@link android.preference.Preference} 時,使用目前 (或預設) 值加以初始化。
</li>
<li>在系統要求時提供預設值。</li>
<li>如果 {@link android.preference.Preference} 提供自己的 UI (例如對話方塊),儲存並還原狀態以處理生命週期變更 (例如,當使用者旋轉螢幕時)。
</li>
</ul>
<p>以下各節說明如何完成這些工作。</p>
<h3 id="CustomSelected">指定使用者介面</h3>
<p>如果您直接延伸 {@link android.preference.Preference} 類別,必須實作 {@link android.preference.Preference#onClick()} 以定義使用者選取項目時的動作。
不過,大多數自訂設定會延伸 {@link android.preference.DialogPreference} 來顯示對話方塊,以簡化程序。
延伸 {@link
android.preference.DialogPreference} 時,您必須在類別建構函式期間呼叫 {@link
android.preference.DialogPreference#setDialogLayoutResource setDialogLayoutResourcs()},以指定對話方塊的版面配置。
</p>
<p>例如,下列為自訂 {@link
android.preference.DialogPreference} 的建構函式,該偏好設定宣告版面配置並指定預設正值和負值對話方塊按鈕的文字:
</p>
<pre>
public class NumberPickerPreference extends DialogPreference {
public NumberPickerPreference(Context context, AttributeSet attrs) {
super(context, attrs);
setDialogLayoutResource(R.layout.numberpicker_dialog);
setPositiveButtonText(android.R.string.ok);
setNegativeButtonText(android.R.string.cancel);
setDialogIcon(null);
}
...
}
</pre>
<h3 id="CustomSave">儲存設定值</h3>
<p>您可以呼叫其中一個 {@link
android.preference.Preference} 類別的 {@code persist*()} 方法隨時儲存設定值,例如,如果設定值是整數,使用 {@link
android.preference.Preference#persistInt persistInt()},或者使用 {@link android.preference.Preference#persistBoolean persistBoolean()} 儲存布林值。
</p>
<p class="note"><strong>注意:</strong>每個 {@link android.preference.Preference} 只能儲存一個資料類型,因此您必須使用適合您自訂 {@link android.preference.Preference} 使用之資料類型的 {@code persist*()} 方法。
</p>
<p>當您選擇保留設定時,可以依據您延伸的 {@link
android.preference.Preference} 類別加以設定。如果您延伸 {@link
android.preference.DialogPreference},則應該只在對話方塊因正值結果 (使用者選取 [確定] 按鈕) 關閉時保留該值。
</p>
<p>當 {@link android.preference.DialogPreference} 關閉時,系統會呼叫 {@link
android.preference.DialogPreference#onDialogClosed onDialogClosed()} 方法。這個方法包括一個布林值引數,指定使用者結果是否為「正值」&mdash; 如果值為
<code>true</code>,則表示使用者選取正值按鈕,而您應該儲存新值。
例如:
</p>
<pre>
&#64;Override
protected void onDialogClosed(boolean positiveResult) {
// When the user selects "OK", persist the new value
if (positiveResult) {
persistInt(mNewValue);
}
}
</pre>
<p>在此範例中,<code>mNewValue</code> 是保留設定目前值的類別成員。
呼叫 {@link android.preference.Preference#persistInt persistInt()} 可將值儲存到 {@link android.content.SharedPreferences} 檔案 (自動使用 XML 檔案中為此 {@link android.preference.Preference} 指定的索引鍵)。
</p>
<h3 id="CustomInitialize">初始化目前值</h3>
<p>當系統將您的 {@link android.preference.Preference} 新增到畫面時,會呼叫 {@link android.preference.Preference#onSetInitialValue onSetInitialValue()} 以通知您設定是否有持續值。
如果沒有持續值,這個呼叫會提供您預設值。
</p>
<p>{@link android.preference.Preference#onSetInitialValue onSetInitialValue()} 方法會傳送布林值 <code>restorePersistedValue</code>,以指出該設定的值是否已經持續。
如果是 <code>true</code>,則您應該呼叫其中一個 {@link
android.preference.Preference} 類別的 {@code getPersisted*()} 方法以擷取持續值,例如,如果為整數值,可使用 {@link
android.preference.Preference#getPersistedInt getPersistedInt()}。
您通常都會想要擷取持續值,如此您可以正確的更新 UI 以反映之前儲存的值。
</p>
<p>如果 <code>restorePersistedValue</code> 是 <code>false</code>,則您應該使用在第二引數中傳送的預設值。
</p>
<pre>
&#64;Override
protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) {
if (restorePersistedValue) {
// Restore existing state
mCurrentValue = this.getPersistedInt(DEFAULT_VALUE);
} else {
// Set default state from the XML attribute
mCurrentValue = (Integer) defaultValue;
persistInt(mCurrentValue);
}
}
</pre>
<p>在實際上沒有持續值或沒有索引鍵的情況下,每個 {@code getPersisted*()} 方法會採用指定要使用之預設值的引數。
在上述範例中,會使用本機常數來指定預設值,以避免 {@link
android.preference.Preference#getPersistedInt getPersistedInt()} 無法傳回持續值。
</p>
<p class="caution"><strong>注意:</strong>您<strong>無法</strong>使用 <code>defaultValue</code> 作為 {@code getPersisted*()} 方法中的預設值,因為當 <code>restorePersistedValue</code> 為 <code>true</code> 時,其值永遠是 null。
</p>
<h3 id="CustomDefault">提供預設值</h3>
<p>如果 {@link android.preference.Preference} 類別的執行個體指定預設值 (包含 {@code android:defaultValue} 屬性),則系統會在將物件具現化時呼叫 {@link android.preference.Preference#onGetDefaultValue
onGetDefaultValue()},以擷取值。
您必須實作此方法,才能讓系統將預設值儲存在 {@link
android.content.SharedPreferences} 中。
例如:</p>
<pre>
&#64;Override
protected Object onGetDefaultValue(TypedArray a, int index) {
return a.getInteger(index, DEFAULT_VALUE);
}
</pre>
<p>方法引數可以提供您所需的所有物件:屬性陣列,以及您必須擷取之 {@code android:defaultValue} 的索引位置。
您必須實作此方法以便從屬性擷取預設值的原因,是因為您必須在未定義值的情況為屬性指定一個本機預設值。
</p>
<h3 id="CustomSaveState">儲存和還原偏好設定狀態</h3>
<p>如同版面配置中的 {@link android.view.View},您的 {@link android.preference.Preference} 子類別負責在 Activity 或片段重新啟動 (例如,當使用者旋轉螢幕時) 時,儲存和還原其狀態。
如要正確的儲存和還原 {@link android.preference.Preference} 類別的狀態,您必須實作生命週期回呼方法 {@link android.preference.Preference#onSaveInstanceState
onSaveInstanceState()} 和 {@link
android.preference.Preference#onRestoreInstanceState onRestoreInstanceState()}。
</p>
<p>您 {@link android.preference.Preference} 的狀態由實作 {@link android.os.Parcelable} 介面的物件定義。
Android 架構為您提供這類物件作為定義狀態物件的起始點:{@link
android.preference.Preference.BaseSavedState} 類別。
</p>
<p>如要定義 {@link android.preference.Preference} 類別儲存狀態的方法,您應該延伸 {@link android.preference.Preference.BaseSavedState} 類別。
您只需要覆寫幾個方法,然後定義 {@link android.preference.Preference.BaseSavedState#CREATOR}物件。
</p>
<p>對於大多數應用程式而言,如果您的 {@link android.preference.Preference} 子類別儲存整數以外的資料類型,您可以複製下列實作,然後變更處理 {@code value} 的行即可。
</p>
<pre>
private static class SavedState extends BaseSavedState {
// Member that holds the setting's value
// Change this data type to match the type saved by your Preference
int value;
public SavedState(Parcelable superState) {
super(superState);
}
public SavedState(Parcel source) {
super(source);
// Get the current preference's value
value = source.readInt(); // Change this to read the appropriate data type
}
&#64;Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
// Write the preference's value
dest.writeInt(value); // Change this to write the appropriate data type
}
// Standard creator object using an instance of this class
public static final Parcelable.Creator&lt;SavedState> CREATOR =
new Parcelable.Creator&lt;SavedState>() {
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
}
</pre>
<p>將上述 {@link android.preference.Preference.BaseSavedState} 實作新增到您的應用程式 (通常做為 {@link android.preference.Preference} 子類別的子類別) 之後,您需要針對 {@link android.preference.Preference} 子類別實作 {@link android.preference.Preference#onSaveInstanceState
onSaveInstanceState()} 和 {@link
android.preference.Preference#onRestoreInstanceState onRestoreInstanceState()} 方法。
</p>
<p>例如:</p>
<pre>
&#64;Override
protected Parcelable onSaveInstanceState() {
final Parcelable superState = super.onSaveInstanceState();
// Check whether this Preference is persistent (continually saved)
if (isPersistent()) {
// No need to save instance state since it's persistent,
// use superclass state
return superState;
}
// Create instance of custom BaseSavedState
final SavedState myState = new SavedState(superState);
// Set the state's value with the class member that holds current
// setting value
myState.value = mNewValue;
return myState;
}
&#64;Override
protected void onRestoreInstanceState(Parcelable state) {
// Check whether we saved the state in onSaveInstanceState
if (state == null || !state.getClass().equals(SavedState.class)) {
// Didn't save the state, so call superclass
super.onRestoreInstanceState(state);
return;
}
// Cast state to custom BaseSavedState and pass to superclass
SavedState myState = (SavedState) state;
super.onRestoreInstanceState(myState.getSuperState());
// Set this Preference's widget to reflect the restored state
mNumberPicker.setValue(myState.value);
}
</pre>