• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1page.title=設定
2page.tags=偏好設定、偏好設定 Activity、偏好設定片段
3
4@jd:body
5
6
7<div id="qv-wrapper">
8<div id="qv">
9
10<h2>本文件內容</h2>
11<ol>
12  <li><a href="#Overview">總覽</a>
13    <ol>
14      <li><a href="#SettingTypes">偏好設定</a></li>
15    </ol>
16  </li>
17  <li><a href="#DefiningPrefs">在 XML 中定義偏好設定</a>
18    <ol>
19      <li><a href="#Groups">建立設定群組</a></li>
20      <li><a href="#Intents">使用意圖</a></li>
21    </ol>
22  </li>
23  <li><a href="#Activity">建立偏好設定 Activity</a></li>
24  <li><a href="#Fragment">使用偏好設定片段</a></li>
25  <li><a href="#Defaults">設定預設值</a></li>
26  <li><a href="#PreferenceHeaders">使用偏好設定標頭</a>
27    <ol>
28      <li><a href="#CreateHeaders">建立標頭檔案</a></li>
29      <li><a href="#DisplayHeaders">顯示標頭</a></li>
30      <li><a href="#BackCompatHeaders">使用偏好設定標頭支援舊版</a></li>
31    </ol>
32  </li>
33  <li><a href="#ReadingPrefs">讀取偏好設定</a>
34    <ol>
35      <li><a href="#Listening">接聽偏好設定變更</a></li>
36    </ol>
37  </li>
38  <li><a href="#NetworkUsage">管理網路使用量</a></li>
39  <li><a href="#Custom">建置自訂偏好設定</a>
40    <ol>
41      <li><a href="#CustomSelected">指定使用者介面</a></li>
42      <li><a href="#CustomSave">儲存設定值</a></li>
43      <li><a href="#CustomInitialize">初始化目前值</a></li>
44      <li><a href="#CustomDefault">提供預設值</a></li>
45      <li><a href="#CustomSaveState">儲存和還原偏好設定狀態</a></li>
46    </ol>
47  </li>
48</ol>
49
50<h2>重要類別</h2>
51<ol>
52  <li>{@link android.preference.Preference}</li>
53  <li>{@link android.preference.PreferenceActivity}</li>
54  <li>{@link android.preference.PreferenceFragment}</li>
55</ol>
56
57
58<h2>另請參閱</h2>
59<ol>
60  <li><a href="{@docRoot}design/patterns/settings.html">設定設計指南</a></li>
61</ol>
62</div>
63</div>
64
65
66
67
68<p>應用程式通常會包含可讓使用者修改應用程式功能和行為的設定。例如,有些應用程式可讓使用者指定是否啟用通知,或指定應用程式與雲端同步資料的頻率。
69
70</p>
71
72<p>如果您想要為應用程式提供設定,應該使用 Android {@link android.preference.Preference} API 建置與其他 Android 應用程式使用者體驗一致的介面 (包含系統設定)。
73
74本文件說明如何使用 {@link android.preference.Preference} API 建置應用程式設定。
75</p>
76
77<div class="note design">
78<p><strong>設定設計</strong></p>
79  <p>如要瞭解如何設計設定,請參閱<a href="{@docRoot}design/patterns/settings.html">設定</a>設計指南。</p>
80</div>
81
82
83<img src="{@docRoot}images/ui/settings/settings.png" alt="" width="435" />
84<p class="img-caption"><strong>圖 1.</strong>Android 簡訊應用程式設定的螢幕擷取畫面。
85選取一個 {@link android.preference.Preference} 定義的項目可以開啟介面變更設定。
86</p>
87
88
89
90
91<h2 id="Overview">總覽</h2>
92
93<p>現在不使用 {@link android.view.View} 物件建置使用者介面,而是使用您在 XML 檔案中所宣告 {@link android.preference.Preference} 類別的各種子類別來建置設定。
94
95</p>
96
97<p>一個 {@link android.preference.Preference} 物件是單一設定的建置區塊。
98每個 {@link android.preference.Preference} 都以項目的形式在清單中顯示,並為使用者提供適當的 UI 以修改設定。
99例如,{@link
100android.preference.CheckBoxPreference} 可以建立顯示核取方塊的清單項目,而 {@link
101android.preference.ListPreference} 可以建立開啟對話方塊 (其中包含選擇清單) 的項目。</p>
102
103<p>每個您新增的 {@link android.preference.Preference} 都會有一個對應的鍵值配對,系統可使用此鍵值對將設定儲存到您應用程式設定的預設 {@link android.content.SharedPreferences} 檔案。
104
105當使用者變更設定,系統會為您更新 {@link android.content.SharedPreferences} 檔案中的對應值。
106您唯一需要與關聯的 {@link android.content.SharedPreferences} 檔案直接互動的時候,是當您需要讀取值才能根據使用者設定判斷應用程式行為時。
107
108</p>
109
110<p>儲存在 {@link android.content.SharedPreferences} 的每個設定值可以是下列其中一個資料類型:
111</p>
112
113<ul>
114  <li>布林值</li>
115  <li>浮動</li>
116  <li>整數</li>
117  <li>長整數</li>
118  <li>字串</li>
119  <li>字串 {@link java.util.Set}</li>
120</ul>
121
122<p>由於您的應用程式設定 UI 是使用 {@link android.preference.Preference} 物件,而不是 {@link android.view.View} 物件建置,因此您需要使用專門的 {@link android.app.Activity} 或 {@link android.app.Fragment} 子類別來顯示清單設定:
123
124
125</p>
126
127<ul>
128  <li>如果應用程式支援的 Android 版本早於 3.0 (API 級別 10 及較早版本),您必須以 {@link android.preference.PreferenceActivity} 類別延伸的形式建置 Activity。
129</li>
130  <li>在 Android 3.0 及更新版本上,您應該使用傳統 {@link android.app.Activity},它託管了顯示應用程式設定的 {@link android.preference.PreferenceFragment}。
131
132然而,當您有多個設定群組時,還可以使用 {@link android.preference.PreferenceActivity} 在大螢幕建立兩個面板的版面配置。
133</li>
134</ul>
135
136<p>如何設定 {@link android.preference.PreferenceActivity} 和 {@link
137android.preference.PreferenceFragment} 執行個體在<a href="#Activity">建立偏好設定 Activity</a> 和<a href="#Fragment">使用偏好設定片段</a>小節中有相關說明。
138</p>
139
140
141<h3 id="SettingTypes">偏好設定</h3>
142
143<p>應用程式的每個設定都會以 {@link
144android.preference.Preference} 類別的特定子類別代表。每個子類別包含一組核心屬性,可讓您為設定指定標題等項目和預設值。
145每個子類別還提供自己專屬的屬性和使用者介面。
146例如,圖 1 顯示簡訊應用程式設定的螢幕擷取畫面。
147設定畫面中的每個清單項目都由不同的 {@link
148android.preference.Preference} 物件支援。</p>
149
150<p>下列為幾個最常見的偏好設定:</p>
151
152<dl>
153  <dt>{@link android.preference.CheckBoxPreference}</dt>
154  <dd>為啟用或停用的設定顯示含有核取方塊的項目。儲存的值是布林值 (如果選取 <code>true</code>)。
155</dd>
156
157  <dt>{@link android.preference.ListPreference}</dt>
158  <dd>開啟含有選項按鈕清單的對話方塊。儲存的值可以是任何支援的值類型 (如上所列)。
159</dd>
160
161  <dt>{@link android.preference.EditTextPreference}</dt>
162  <dd>開啟含有 {@link android.widget.EditText} 小工具的對話方塊。儲存的值是 {@link
163java.lang.String}。</dd>
164</dl>
165
166<p>請參閱 {@link android.preference.Preference} 類別,以取得所有其他子類別及其對應屬性的清單。
167</p>
168
169<p>當然,內建類別無法滿足所有需要,您的應用程式可能需要更專門的功能。
170例如,平台目前無法提供 {@link
171android.preference.Preference} 類別以選取數字或日期。因此,您可能需要定義自己的 {@link android.preference.Preference} 子類別。
172如需執行此操作的協助,請參閱<a href="#Custom">建置自訂偏好設定</a>。</p>
173
174
175
176<h2 id="DefiningPrefs">在 XML 中定義偏好設定</h2>
177
178<p>雖然您可以在執行階段將新的 {@link android.preference.Preference} 物件具現化,但您仍應該在 XML 中定義設定清單,並在其中包含 {@link android.preference.Preference} 物件的階層。
179
180使用 XML 檔案定義設定集合是較建議的做法,因為該檔案提供的易讀結構很容易更新。
181而且,雖然您仍然可以在執行階段修改集合,但您的應用程式設定通常是預先定義好的。
182</p>
183
184<p>每個 {@link android.preference.Preference} 子類別都可透過與類別名稱相符的 XML 元素進行宣告,例如 {@code &lt;CheckBoxPreference&gt;}。
185</p>
186
187<p>您必須將 XML 檔案儲存在 {@code res/xml/} 目錄中。雖然您可以自由命名檔案,但在傳統上會命名為 {@code preferences.xml}。
188您通常只需要一個檔案,因為階層 (會開啟自己的設定清單) 中的子目錄是透過 {@link android.preference.PreferenceScreen} 的巢狀執行個體進行宣告。
189
190</p>
191
192<p class="note"><strong>注意:</strong>如果您想要為設定建立多個面板的版面配置,則您需要為每個片段準備個別的 XML 檔案。
193</p>
194
195<p>XML 檔案的根節點必須是 {@link android.preference.PreferenceScreen
196&lt;PreferenceScreen&gt;} 元素。您要將每個 {@link
197android.preference.Preference} 新增到此元素內。您在 {@link android.preference.PreferenceScreen &lt;PreferenceScreen&gt;} 元素內新增的每個子項會在設定清單中顯示為單一項目。
198
199</p>
200
201<p>例如:</p>
202
203<pre>
204&lt;?xml version="1.0" encoding="utf-8"?>
205&lt;PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
206    &lt;CheckBoxPreference
207        android:key="pref_sync"
208        android:title="@string/pref_sync"
209        android:summary="@string/pref_sync_summ"
210        android:defaultValue="true" />
211    &lt;ListPreference
212        android:dependency="pref_sync"
213        android:key="pref_syncConnectionType"
214        android:title="@string/pref_syncConnectionType"
215        android:dialogTitle="@string/pref_syncConnectionType"
216        android:entries="@array/pref_syncConnectionTypes_entries"
217        android:entryValues="@array/pref_syncConnectionTypes_values"
218        android:defaultValue="@string/pref_syncConnectionTypes_default" />
219&lt;/PreferenceScreen>
220</pre>
221
222<p>此範例中有一個 {@link android.preference.CheckBoxPreference} 和一個 {@link
223android.preference.ListPreference}。這兩個項目都包含下列三個屬性:</p>
224
225<dl>
226  <dt>{@code android:key}</dt>
227  <dd>需要這個屬性才能保留資料值的偏好設定。它會指定當系統將此設定值儲存於 {@link
228android.content.SharedPreferences} 時要使用的唯一索引鍵 (字串)。
229
230  <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
231android:fragment}</a> 屬性)。
232
233</p>
234  </dd>
235  <dt>{@code android:title}</dt>
236  <dd>這可為設定提供使用者可見的名稱。</dd>
237  <dt>{@code android:defaultValue}</dt>
238  <dd>這可指定系統在 {@link
239android.content.SharedPreferences} 檔案中應設定的初始值。您應該為所有設定提供預設值。
240</dd>
241</dl>
242
243<p>如需所有其他支援的屬性相關資訊,請參閱 {@link
244android.preference.Preference} (及個別子類別) 文件。</p>
245
246
247<div class="figure" style="width:300px">
248  <img src="{@docRoot}images/ui/settings/settings-titles.png" alt="" />
249  <p class="img-caption"><strong>圖 2.</strong>設定含有標題的類別。
250 <br/><b>1.</b>類別以 {@link
251android.preference.PreferenceCategory &lt;PreferenceCategory&gt;} 元素指定。 <br/><b>2.</b>標題以 {@code android:title} 屬性指定。
252</p>
253</div>
254
255
256<p>如果您的設定清單超過約 10 個項目,您可以新增標題來定義設定群組,或在分開的畫面顯示這些群組。
257
258這些選項在下列幾節有詳細的描述。</p>
259
260
261<h3 id="Groups">建立設定群組</h3>
262
263<p>如果您的清單有 10 個以上的項目,掃描、理解和處理這些項目對使用者而言可能會很困難。
264如要解決這個問題,可將部分或所有設定分成不同的群組,有效地將一長串清單分成多個簡短的清單。
265
266一組包含相關設定的群組可以下列其中一種方式顯示:</p>
267
268<ul>
269  <li><a href="#Titles">使用標題</a></li>
270  <li><a href="#Subscreens">使用子畫面</a></li>
271</ul>
272
273<p>您可以使用上述一種或兩種分組技巧來整理您的應用程式設定。決定要使用哪種方法或如何分割設定時,您應該要依照 Android 設計<a href="{@docRoot}design/patterns/settings.html">設定</a>指南中的指導方針進行。
274
275</p>
276
277
278<h4 id="Titles">使用標題</h4>
279
280<p>如果您想要在設定群組間使用標題區分 (如圖 2 所示),將 {@link android.preference.Preference} 物件的每個群組放入 {@link
281android.preference.PreferenceCategory}。
282</p>
283
284<p>例如:</p>
285
286<pre>
287&lt;PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
288    &lt;PreferenceCategory
289        android:title="&#64;string/pref_sms_storage_title"
290        android:key="pref_key_storage_settings">
291        &lt;CheckBoxPreference
292            android:key="pref_key_auto_delete"
293            android:summary="&#64;string/pref_summary_auto_delete"
294            android:title="&#64;string/pref_title_auto_delete"
295            android:defaultValue="false"... />
296        &lt;Preference
297            android:key="pref_key_sms_delete_limit"
298            android:dependency="pref_key_auto_delete"
299            android:summary="&#64;string/pref_summary_delete_limit"
300            android:title="&#64;string/pref_title_sms_delete"... />
301        &lt;Preference
302            android:key="pref_key_mms_delete_limit"
303            android:dependency="pref_key_auto_delete"
304            android:summary="&#64;string/pref_summary_delete_limit"
305            android:title="&#64;string/pref_title_mms_delete" ... />
306    &lt;/PreferenceCategory>
307    ...
308&lt;/PreferenceScreen>
309</pre>
310
311
312<h4 id="Subscreens">使用子畫面</h4>
313
314<p>如果您想將設定群組放入子畫面 (如圖 3 所示),將 {@link android.preference.Preference} 物件的群組放入 {@link
315android.preference.PreferenceScreen}。
316</p>
317
318<img src="{@docRoot}images/ui/settings/settings-subscreen.png" alt="" />
319<p class="img-caption"><strong>圖 3.</strong>設定子畫面。{@code
320&lt;PreferenceScreen&gt;} 元素建立的項目會在選取時開啟獨立的清單以顯示巢狀設定。
321</p>
322
323<p>例如:</p>
324
325<pre>
326&lt;PreferenceScreen  xmlns:android="http://schemas.android.com/apk/res/android">
327    &lt;!-- opens a subscreen of settings -->
328    &lt;PreferenceScreen
329        android:key="button_voicemail_category_key"
330        android:title="&#64;string/voicemail"
331        android:persistent="false">
332        &lt;ListPreference
333            android:key="button_voicemail_provider_key"
334            android:title="&#64;string/voicemail_provider" ... />
335        &lt;!-- opens another nested subscreen -->
336        &lt;PreferenceScreen
337            android:key="button_voicemail_setting_key"
338            android:title="&#64;string/voicemail_settings"
339            android:persistent="false">
340            ...
341        &lt;/PreferenceScreen>
342        &lt;RingtonePreference
343            android:key="button_voicemail_ringtone_key"
344            android:title="&#64;string/voicemail_ringtone_title"
345            android:ringtoneType="notification" ... />
346        ...
347    &lt;/PreferenceScreen>
348    ...
349&lt;/PreferenceScreen>
350</pre>
351
352
353<h3 id="Intents">使用意圖</h3>
354
355<p>在某些情況下,您可能會希望偏好設定項目開啟不同的 Activity 而不是設定畫面,例如,開啟網路瀏覽器以檢視網頁。
356如要在使用者選取偏好設定項目時呼叫 {@link
357android.content.Intent},請新增 {@code &lt;intent&gt;} 元素做為對應 {@code &lt;Preference&gt;} 元素的子項。
358</p>
359
360<p>例如,您可以使用下列方法透過偏好設定項目開啟網頁:</p>
361
362<pre>
363&lt;Preference android:title="@string/prefs_web_page" >
364    &lt;intent android:action="android.intent.action.VIEW"
365            android:data="http://www.example.com" />
366&lt;/Preference>
367</pre>
368
369<p>您可以使用下列屬性建立隱含和明確意圖:</p>
370
371<dl>
372  <dt>{@code android:action}</dt>
373    <dd>根據 {@link android.content.Intent#setAction setAction()} 方法指派的動作。
374</dd>
375  <dt>{@code android:data}</dt>
376    <dd>根據 {@link android.content.Intent#setData setData()} 方法指派的資料。</dd>
377  <dt>{@code android:mimeType}</dt>
378    <dd>根據 {@link android.content.Intent#setType setType()} 方法指派的 MIME 類型。
379</dd>
380  <dt>{@code android:targetClass}</dt>
381    <dd>根據 {@link android.content.Intent#setComponent
382setComponent()} 方法指派的元件名稱類別部分。</dd>
383  <dt>{@code android:targetPackage}</dt>
384    <dd>根據 {@link
385android.content.Intent#setComponent setComponent()} 方法指派的元件名稱封裝部分。</dd>
386</dl>
387
388
389
390<h2 id="Activity">建立偏好設定 Activity</h2>
391
392<p>如要在 Activity 中顯示設定,延伸 {@link
393android.preference.PreferenceActivity} 類別。這是傳統 {@link
394android.app.Activity} 類別的延伸,可根據 {@link
395android.preference.Preference} 物件的階層顯示設定清單。當使用者進行變更時,{@link android.preference.PreferenceActivity} 會自動保留與每個 {@link
396android.preference.Preference} 關聯的設定。
397</p>
398
399<p class="note"><strong>注意:</strong>如果您針對 Android 3.0 及更新版本開發應用程式,您應該改為使用 {@link android.preference.PreferenceFragment}。
400前往下一個<a href="#Fragment">使用偏好設定片段</a>章節。
401</p>
402
403<p>最需要注意的一件事就是,不要在 {@link
404android.preference.PreferenceActivity#onCreate onCreate()} 呼叫期間載入檢視的版面配置。您應該要呼叫 {@link
405android.preference.PreferenceActivity#addPreferencesFromResource addPreferencesFromResource()},將您在 XML 檔案中宣告的偏好設定新增到 Activity 中。
406例如,下列為功能 {@link android.preference.PreferenceActivity} 所需的基本程式碼:
407</p>
408
409<pre>
410public class SettingsActivity extends PreferenceActivity {
411    &#64;Override
412    public void onCreate(Bundle savedInstanceState) {
413        super.onCreate(savedInstanceState);
414        addPreferencesFromResource(R.xml.preferences);
415    }
416}
417</pre>
418
419<p>事實上,這個程式碼對某些應用程式而言已經足夠,因為使用者修改偏好設定後,系統會將變更儲存到預設 {@link android.content.SharedPreferences} 檔案,當您需要檢查使用者設定時,您的其他應用程式元件就能進行讀取。
420
421但是,許多應用程式需要更多一點程式碼,以接聽對偏好設定進行的變更。
422如需在 {@link android.content.SharedPreferences} 檔案接聽變更的相關資訊,請參閱<a href="#ReadingPrefs">讀取偏好設定</a>。
423
424</p>
425
426
427
428
429<h2 id="Fragment">使用偏好設定片段</h2>
430
431<p>如果您針對 Android 3.0 (API 級別 11) 及更新版本進行開發,您應該使用 {@link
432android.preference.PreferenceFragment} 顯示 {@link android.preference.Preference} 物件清單。
433您可以將 {@link android.preference.PreferenceFragment} 新增到任何 Activity &mdash; 您不需要使用 {@link android.preference.PreferenceActivity}。
434</p>
435
436<p><a href="{@docRoot}guide/components/fragments.html">片段</a>單就 Activity 而言,可為您的應用程式提供更有彈性的架構,無論您建置哪一種 Activity 都一樣。
437
438因此,我們建議您盡可能使用 {@link
439android.preference.PreferenceFragment} 來控制設定的顯示,而不要使用 {@link
440android.preference.PreferenceActivity}。</p>
441
442<p>實作 {@link android.preference.PreferenceFragment} 可以很簡單,只要定義 {@link android.preference.PreferenceFragment#onCreate onCreate()} 方法,透過 {@link android.preference.PreferenceFragment#addPreferencesFromResource
443addPreferencesFromResource()} 載入偏好設定檔案。
444
445例如:</p>
446
447<pre>
448public static class SettingsFragment extends PreferenceFragment {
449    &#64;Override
450    public void onCreate(Bundle savedInstanceState) {
451        super.onCreate(savedInstanceState);
452
453        // Load the preferences from an XML resource
454        addPreferencesFromResource(R.xml.preferences);
455    }
456    ...
457}
458</pre>
459
460<p>之後,您可以將此片段新增至 {@link android.app.Activity},做法與任何其他
461{@link android.app.Fragment} 一樣。例如:</p>
462
463<pre>
464public class SettingsActivity extends Activity {
465    &#64;Override
466    protected void onCreate(Bundle savedInstanceState) {
467        super.onCreate(savedInstanceState);
468
469        // Display the fragment as the main content.
470        getFragmentManager().beginTransaction()
471                .replace(android.R.id.content, new SettingsFragment())
472                .commit();
473    }
474}
475</pre>
476
477<p class="note"><strong>注意:</strong>{@link android.preference.PreferenceFragment} 沒有自己的 {@link android.content.Context} 物件。
478如果您需要 {@link android.content.Context} 物件,可以呼叫 {@link android.app.Fragment#getActivity()}。
479不過,必須小心,只能在片段附加到 Activity 時才能呼叫 {@link android.app.Fragment#getActivity()}。
480如果未附加片段,或是在生命週期期間中斷連結,{@link
481android.app.Fragment#getActivity()} 將傳回 null。
482</p>
483
484
485<h2 id="Defaults">設定預設值</h2>
486
487<p>您建立的偏好設定可能為應用程式定義了一些重要的行為,因此當使用者第一次開啟您的應用程式時,務必使用每個 {@link android.preference.Preference} 預設值來初始化關聯的 {@link android.content.SharedPreferences} 檔案。
488
489
490</p>
491
492<p>您必須要做的第一件事,就是使用 {@code android:defaultValue} 屬性指定 XML 檔案中每個 {@link
493android.preference.Preference} 物件的預設值。
494值可以是適用於對應 {@link android.preference.Preference} 物件的任何資料類型。
495例如:
496</p>
497
498<pre>
499&lt;!-- default value is a boolean -->
500&lt;CheckBoxPreference
501    android:defaultValue="true"
502    ... />
503
504&lt;!-- default value is a string -->
505&lt;ListPreference
506    android:defaultValue="@string/pref_syncConnectionTypes_default"
507    ... />
508</pre>
509
510<p>之後,從您應用程式主 Activity &mdash; 以及使用者第一次進入您應用程式所使用的任何其他 Activity &mdash; 的 {@link android.app.Activity#onCreate onCreate()} 方法呼叫 {@link android.preference.PreferenceManager#setDefaultValues
511setDefaultValues()}:
512
513</p>
514
515<pre>
516PreferenceManager.setDefaultValues(this, R.xml.advanced_preferences, false);
517</pre>
518
519<p>在 {@link android.app.Activity#onCreate onCreate()} 期間呼叫它,可確保您的應用程式正確地以預設值初始化,您的應用程式可能需要讀取這些預設值,才能判斷一些行為 (例如,使用行動網路時是否可下載資料)。
520
521
522</p>
523
524<p>這個方法採用三種引數:</p>
525<ul>
526  <li>您的應用程式 {@link android.content.Context}。</li>
527  <li>您要設定預設值之偏好設定 XML 檔案的資源 ID。</li>
528  <li>布林值指出預設值是否要設定一次以上。
529<p>如果為 <code>false</code>,系統只會在過去從未呼叫此方法時設定預設值 (或者預設值共用偏好設定檔案的 {@link android.preference.PreferenceManager#KEY_HAS_SET_DEFAULT_VALUES} 為 false)。
530
531</p></li>
532</ul>
533
534<p>只要將第三個引數設為 <code>false</code>,您可以在每次 Activity 啟動時很安全地呼叫此方法,而不會將使用者儲存的偏好設定重設為預設值。
535
536不過,如果您將它設為 <code>true</code>,會將任何之前的值覆寫為預設值。
537</p>
538
539
540
541<h2 id="PreferenceHeaders">使用偏好設定標頭</h2>
542
543<p>在少數情況下,您可能會想將設定設計為只在第一個畫面顯示<a href="#Subscreens">子畫面</a>清單(與系統設定應用程式一樣,如圖 4 和 5 所示)。
544
545當您為 Android 3.0 及更新版本開發這類設計時,您應該使用 Android 3.0 的新「標頭」功能,而不是使用巢狀 {@link android.preference.PreferenceScreen} 元素建置子畫面。
546
547</p>
548
549<p>如要使用標頭建置設定,您必須:</p>
550<ol>
551  <li>將每個設定群組分成不同的 {@link
552android.preference.PreferenceFragment} 執行個體。也就是說,每個設定群組需要一個獨立的 XML 檔案。
553</li>
554  <li>建立一個 XML 標頭檔案,其中列出每個設定群組以及宣告哪些片段包含對應的設定清單。
555</li>
556  <li>延伸 {@link android.preference.PreferenceActivity} 類別以託管您的設定。</li>
557  <li>實作 {@link
558android.preference.PreferenceActivity#onBuildHeaders onBuildHeaders()} 回呼以指定標頭檔案。
559</li>
560</ol>
561
562<p>使用這個設計最大的好處在於在大螢幕執行時,
563{@link android.preference.PreferenceActivity} 會自動顯示兩個面板的版面配置,如圖 4 所示。</p>
564
565<p>即使應用程式支援的 Android 版本較 3.0 舊,您還是可以建置應用程式在新版的裝置上使用 {@link android.preference.PreferenceFragment} 顯示兩個面板,同時仍然支援舊版裝置上的傳統多畫面階層 (請參閱<a href="#BackCompatHeaders">使用偏好設定標頭支援舊版</a>)。
566
567
568
569</p>
570
571<img src="{@docRoot}images/ui/settings/settings-headers-tablet.png" alt="" />
572<p class="img-caption"><strong>圖 4.</strong>含標頭的兩個面板版面配置。 <br/><b>1.</b>標頭以 XML 標頭檔案定義。
573 <br/><b>2.</b>每個設定群組是由標頭檔案 {@code &lt;header&gt;} 元素指定的{@link android.preference.PreferenceFragment} 所定義。
574
575</p>
576
577<img src="{@docRoot}images/ui/settings/settings-headers-handset.png" alt="" />
578<p class="img-caption"><strong>圖 5.</strong>含設定標頭的手機裝置。選取項目後,關聯的 {@link android.preference.PreferenceFragment} 會取代標頭。
579
580</p>
581
582
583<h3 id="CreateHeaders" style="clear:left">建立標頭檔案</h3>
584
585<p>您標頭清單中的每個設定群組是由根 {@code &lt;preference-headers&gt;} 元素中的單一 {@code &lt;header&gt;} 元素指定。
586例如:</p>
587
588<pre>
589&lt;?xml version="1.0" encoding="utf-8"?>
590&lt;preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
591    &lt;header
592        android:fragment="com.example.prefs.SettingsActivity$SettingsFragmentOne"
593        android:title="@string/prefs_category_one"
594        android:summary="@string/prefs_summ_category_one" />
595    &lt;header
596        android:fragment="com.example.prefs.SettingsActivity$SettingsFragmentTwo"
597        android:title="@string/prefs_category_two"
598        android:summary="@string/prefs_summ_category_two" >
599        &lt;!-- key/value pairs can be included as arguments for the fragment. -->
600        &lt;extra android:name="someKey" android:value="someHeaderValue" />
601    &lt;/header>
602&lt;/preference-headers>
603</pre>
604
605<p>有了 {@code android:fragment} 屬性,每個標頭會宣告當使用者選取標頭時,應該開啟的 {@link
606android.preference.PreferenceFragment} 執行個體。</p>
607
608<p>{@code &lt;extras&gt;} 元素可讓您將鍵值配對傳送到 {@link
609android.os.Bundle} 中的片段。片段可以透過呼叫 {@link
610android.app.Fragment#getArguments()} 擷取引數。您可以因各種理由將引數傳送到片段,但其中一個最好的理由是針對每個群組重複使用 {@link
611android.preference.PreferenceFragment} 中相同的子類別,並使用引數指定應載入片段的偏好設定 XML 檔案。
612
613</p>
614
615<p>例如,當每個標頭使用 {@code "settings"} 索引鍵定義 {@code &lt;extra&gt;} 引數時,下列片段可在多個設定群組重複使用:
616</p>
617
618<pre>
619public static class SettingsFragment extends PreferenceFragment {
620    &#64;Override
621    public void onCreate(Bundle savedInstanceState) {
622        super.onCreate(savedInstanceState);
623
624        String settings = getArguments().getString("settings");
625        if ("notifications".equals(settings)) {
626            addPreferencesFromResource(R.xml.settings_wifi);
627        } else if ("sync".equals(settings)) {
628            addPreferencesFromResource(R.xml.settings_sync);
629        }
630    }
631}
632</pre>
633
634
635
636<h3 id="DisplayHeaders">顯示標頭</h3>
637
638<p>如要顯示偏好設定標頭,必須實作 {@link
639android.preference.PreferenceActivity#onBuildHeaders onBuildHeaders()} 回呼方法,並呼叫 {@link android.preference.PreferenceActivity#loadHeadersFromResource
640loadHeadersFromResource()}。
641例如:</p>
642
643<pre>
644public class SettingsActivity extends PreferenceActivity {
645    &#64;Override
646    public void onBuildHeaders(List&lt;Header> target) {
647        loadHeadersFromResource(R.xml.preference_headers, target);
648    }
649}
650</pre>
651
652<p>當使用者從標頭清單選取項目時,系統會開啟關聯的 {@link
653android.preference.PreferenceFragment}。</p>
654
655<p class="note"><strong>注意:</strong>使用偏好設定標頭時,{@link
656android.preference.PreferenceActivity} 的子類別不需要實作 {@link
657android.preference.PreferenceActivity#onCreate onCreate()} 方法,這是因為 Activity 唯一需要做的工作就是載入標頭。
658</p>
659
660
661<h3 id="BackCompatHeaders">使用偏好設定標頭支援舊版</h3>
662
663<p>如果您應用程式支援的 Android 版本比 3.0 舊,您仍然可以在 Android 3.0 及更新版本執行時,使用標頭提供兩個面板的版面配置。
664您只需要建立一個額外的偏好設定 XML 檔案,該檔案要使用行為與標頭項目 (供舊版 Android 使用) 一樣的基本 {@link android.preference.Preference
665&lt;Preference&gt;} 元素。
666
667</p>
668
669<p>但是,不會開啟新的 {@link android.preference.PreferenceScreen},每個 {@link
670android.preference.Preference &lt;Preference&gt;} 元素會傳送一個 {@link android.content.Intent} 到 {@link android.preference.PreferenceActivity},以指定要載入的偏好設定 XML 檔案。
671
672</p>
673
674<p>例如,下列為使用 Android 3.0及更新版本的偏好設定標頭 XML 檔案 ({@code res/xml/preference_headers.xml}):
675</p>
676
677<pre>
678&lt;preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
679    &lt;header
680        android:fragment="com.example.prefs.SettingsFragmentOne"
681        android:title="@string/prefs_category_one"
682        android:summary="@string/prefs_summ_category_one" />
683    &lt;header
684        android:fragment="com.example.prefs.SettingsFragmentTwo"
685        android:title="@string/prefs_category_two"
686        android:summary="@string/prefs_summ_category_two" />
687&lt;/preference-headers>
688</pre>
689
690<p>而,這裡有個偏好設定檔案為 Android 3.0 以下版本提供相同的標頭 ({@code res/xml/preference_headers_legacy.xml}):
691</p>
692
693<pre>
694&lt;PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
695    &lt;Preference
696        android:title="@string/prefs_category_one"
697        android:summary="@string/prefs_summ_category_one"  >
698        &lt;intent
699            android:targetPackage="com.example.prefs"
700            android:targetClass="com.example.prefs.SettingsActivity"
701            android:action="com.example.prefs.PREFS_ONE" />
702    &lt;/Preference>
703    &lt;Preference
704        android:title="@string/prefs_category_two"
705        android:summary="@string/prefs_summ_category_two" >
706        &lt;intent
707            android:targetPackage="com.example.prefs"
708            android:targetClass="com.example.prefs.SettingsActivity"
709            android:action="com.example.prefs.PREFS_TWO" />
710    &lt;/Preference>
711&lt;/PreferenceScreen>
712</pre>
713
714<p>因為 Android 3.0 已加入對 {@code &lt;preference-headers&gt;} 的支援,系統只會在 Androd 3.0 或更新版本執行時,才會呼叫 {@link
715android.preference.PreferenceActivity} 中的 {@link android.preference.PreferenceActivity#onBuildHeaders onBuildHeaders()}。
716如要載入「舊版」標頭檔案 ({@code preference_headers_legacy.xml}),您必須檢查 Android 版本,如果版本比 Android 3.0 更舊 ({@link
717android.os.Build.VERSION_CODES#HONEYCOMB}),呼叫 {@link
718android.preference.PreferenceActivity#addPreferencesFromResource addPreferencesFromResource()} 以載入舊版標頭檔案。
719
720
721例如:</p>
722
723<pre>
724&#64;Override
725public void onCreate(Bundle savedInstanceState) {
726    super.onCreate(savedInstanceState);
727    ...
728
729    if (Build.VERSION.SDK_INT &lt; Build.VERSION_CODES.HONEYCOMB) {
730        // Load the legacy preferences headers
731        addPreferencesFromResource(R.xml.preference_headers_legacy);
732    }
733}
734
735// Called only on Honeycomb and later
736&#64;Override
737public void onBuildHeaders(List&lt;Header> target) {
738   loadHeadersFromResource(R.xml.preference_headers, target);
739}
740</pre>
741
742<p>最後一件要做的事,是處理傳送到 Activity 的 {@link android.content.Intent},以識別要載入的偏好設定檔案。
743擷取意圖的動作,並將它與偏好設定 XML {@code &lt;intent&gt;} 標籤中使用的已知動作字串進行比對:
744</p>
745
746<pre>
747final static String ACTION_PREFS_ONE = "com.example.prefs.PREFS_ONE";
748...
749
750&#64;Override
751public void onCreate(Bundle savedInstanceState) {
752    super.onCreate(savedInstanceState);
753
754    String action = getIntent().getAction();
755    if (action != null &amp;&amp; action.equals(ACTION_PREFS_ONE)) {
756        addPreferencesFromResource(R.xml.preferences);
757    }
758    ...
759
760    else if (Build.VERSION.SDK_INT &lt; Build.VERSION_CODES.HONEYCOMB) {
761        // Load the legacy preferences headers
762        addPreferencesFromResource(R.xml.preference_headers_legacy);
763    }
764}
765</pre>
766
767<p>請注意,{@link
768android.preference.PreferenceActivity#addPreferencesFromResource addPreferencesFromResource()} 的連續呼叫會將所有偏好設定堆疊在單一清單中,因此請確定將條件鏈結到 else-if 陳述式時只會呼叫它一次。
769
770</p>
771
772
773
774
775
776<h2 id="ReadingPrefs">讀取偏好設定</h2>
777
778<p>根據預設,透過呼叫靜態方法 {@link
779android.preference.PreferenceManager#getDefaultSharedPreferences
780PreferenceManager.getDefaultSharedPreferences()},您應用程式中的所有偏好設定會儲存可從應用程式內任何地方存取的檔案中。
781這會傳回 {@link
782android.content.SharedPreferences} 物件,其中包含與您 {@link
783android.preference.PreferenceActivity} 使用之 {@link android.preference.Preference} 物件關聯的所有鍵值配對。
784</p>
785
786<p>例如,下列說明如何從應用程式中的任何其他 Activity 讀取其中一個偏好設定值:
787</p>
788
789<pre>
790SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
791String syncConnPref = sharedPref.getString(SettingsActivity.KEY_PREF_SYNC_CONN, "");
792</pre>
793
794
795
796<h3 id="Listening">接聽偏好設定變更</h3>
797
798<p>使用者變更其中一個偏好設定後,您想要立即收到通知的原因有好幾個。
799如要在任何偏好設定發生變更時收到回呼,實作 {@link android.content.SharedPreferences.OnSharedPreferenceChangeListener
800SharedPreference.OnSharedPreferenceChangeListener} 介面,並呼叫 {@link
801android.content.SharedPreferences#registerOnSharedPreferenceChangeListener
802registerOnSharedPreferenceChangeListener()} 為 {@link android.content.SharedPreferences} 物件註冊接聽器。
803
804</p>
805
806<p>介面只有一個回呼方式 {@link
807android.content.SharedPreferences.OnSharedPreferenceChangeListener#onSharedPreferenceChanged
808onSharedPreferenceChanged()},而且在 Activity 中實作介面可能對您來說會更為容易。
809例如:</p>
810
811<pre>
812public class SettingsActivity extends PreferenceActivity
813                              implements OnSharedPreferenceChangeListener {
814    public static final String KEY_PREF_SYNC_CONN = "pref_syncConnectionType";
815    ...
816
817    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
818        String key) {
819        if (key.equals(KEY_PREF_SYNC_CONN)) {
820            Preference connectionPref = findPreference(key);
821            // Set summary to be the user-description for the selected value
822            connectionPref.setSummary(sharedPreferences.getString(key, ""));
823        }
824    }
825}
826</pre>
827
828<p>在此範例中,方法會檢查是否是針對已知的偏好設定索引鍵設定進行變更。它會呼叫 {@link android.preference.PreferenceActivity#findPreference findPreference()} 以取得變更的 {@link android.preference.Preference} 物件,以便將項目摘要修改為使用者選取的描述。
829
830
831也就是說,當設定為 {@link
832android.preference.ListPreference} 或其他多選擇設定時,如果設定變更為顯示目前狀態 (如圖 5 顯示的休眠設定),您應該呼叫 {@link
833android.preference.Preference#setSummary setSummary()}。
834</p>
835
836<p class="note"><strong>注意:</strong>如 Android 設計文件中有關<a href="{@docRoot}design/patterns/settings.html">設定</a>的說明所述,我們建議您在每次使用者變更偏好設定時更新 {@link android.preference.ListPreference} 的摘要,以描述目前的設定。
837
838</p>
839
840<p>為了在 Activity 中正確管理生命週期,我們建議您分別在 {@link
841android.app.Activity#onResume} 和 {@link android.app.Activity#onPause} 回呼期間,註冊和解決註冊您的 {@link android.content.SharedPreferences.OnSharedPreferenceChangeListener}:
842</p>
843
844<pre>
845&#64;Override
846protected void onResume() {
847    super.onResume();
848    getPreferenceScreen().getSharedPreferences()
849            .registerOnSharedPreferenceChangeListener(this);
850}
851
852&#64;Override
853protected void onPause() {
854    super.onPause();
855    getPreferenceScreen().getSharedPreferences()
856            .unregisterOnSharedPreferenceChangeListener(this);
857}
858</pre>
859
860<p class="caution"><strong>注意:</strong>當您呼叫 {@link
861android.content.SharedPreferences#registerOnSharedPreferenceChangeListener
862registerOnSharedPreferenceChangeListener()} 時,偏好設定管理員目前不會在接聽器儲存強式參照。
863您必須將強式參照儲存到接聽器,否則它會很容易受記憶體回收的影響。
864我們建議您在物件的執行個體資料中保留接聽器參照,如此一來您可以在需要接聽器時隨時使用。
865
866</p>
867
868<p>例如,在下列程式碼中,呼叫器沒有保留接聽器參照。
869因此,接聽器將受到記憶體回收的支配,而且會在未來不明確的時間發生失敗:
870</p>
871
872<pre>
873prefs.registerOnSharedPreferenceChangeListener(
874  // Bad! The listener is subject to garbage collection!
875  new SharedPreferences.OnSharedPreferenceChangeListener() {
876  public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
877    // listener implementation
878  }
879});
880</pre>
881
882<p>將接聽器參照儲存在物件的執行個體資料欄位中,可以在需要接聽器時隨時使用:
883</p>
884
885<pre>
886SharedPreferences.OnSharedPreferenceChangeListener listener =
887    new SharedPreferences.OnSharedPreferenceChangeListener() {
888  public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
889    // listener implementation
890  }
891};
892prefs.registerOnSharedPreferenceChangeListener(listener);
893</pre>
894
895<h2 id="NetworkUsage">管理網路使用量</h2>
896
897
898<p>從 Android 4.0 開始,系統的設定應用程式允許使用者查看應用程式在前景和背景時使用了多少網路資料。
899然後,使用者可以停用個別應用程式的背景資料。
900如要避免使用者停用您的應用程式從背景存取資料,您應該有效率地使用資料連線,並允許使用者透過應用程式設定精簡您的應用程式資料使用量。
901
902<p>
903
904<p>例如,您可以讓使用者控制同步資料的頻率,無論您的應用程式只在 Wi-Fi 上執行上傳/下載、應用程式在漫遊使用資料等。
905使用者有了這些控制項,就比較不會在快要達到在系統設定中設定的限制時停用您應用程式的資料存取,因為他們可以準確地控制您應用程式使用的資料量。
906
907
908</p>
909
910<p>您在 {@link android.preference.PreferenceActivity} 新增所需的偏好設定以控制應用程式的資料習慣後,您應該在宣示說明檔新增 {@link
911android.content.Intent#ACTION_MANAGE_NETWORK_USAGE} 的意圖篩選器。
912例如:</p>
913
914<pre>
915&lt;activity android:name="SettingsActivity" ... >
916    &lt;intent-filter>
917       &lt;action android:name="android.intent.action.MANAGE_NETWORK_USAGE" />
918       &lt;category android:name="android.intent.category.DEFAULT" />
919    &lt;/intent-filter>
920&lt;/activity>
921</pre>
922
923<p>這個意圖篩選器向系統指出,是 Activity 在控制您的應用程式資料使用量。
924因此,當使用者從系統設定應用程式檢查您的應用程式使用了多少資料量時,可以使用 [檢視應用程式設定] 按鈕啟動您的<em></em> {@link android.preference.PreferenceActivity},讓使用者精簡您應用程式使用的資料量。
925
926
927</p>
928
929
930
931
932
933
934
935<h2 id="Custom">建置自訂偏好設定</h2>
936
937<p>Android 架構包含各式各樣的 {@link android.preference.Preference} 子類別,可讓您建置所種不同設定類型的 UI。不過,您可能會發現內建解決方案中可能沒有您所需的設定,例如數字挑選器或日期挑選器。
938
939
940在這類情況下,您需要延伸 {@link android.preference.Preference} 類別或其中一個其他子類別,以建立自訂的偏好設定。
941</p>
942
943<p>當您延伸 {@link android.preference.Preference} 類別時,需要執行幾個重要工作:
944</p>
945
946<ul>
947  <li>指定使用者選取設定時要顯示的使用者介面。</li>
948  <li>視需要儲存設定值。</li>
949  <li>顯示 {@link android.preference.Preference} 時,使用目前 (或預設) 值加以初始化。
950</li>
951  <li>在系統要求時提供預設值。</li>
952  <li>如果 {@link android.preference.Preference} 提供自己的 UI (例如對話方塊),儲存並還原狀態以處理生命週期變更 (例如,當使用者旋轉螢幕時)。
953</li>
954</ul>
955
956<p>以下各節說明如何完成這些工作。</p>
957
958
959
960<h3 id="CustomSelected">指定使用者介面</h3>
961
962  <p>如果您直接延伸 {@link android.preference.Preference} 類別,必須實作 {@link android.preference.Preference#onClick()} 以定義使用者選取項目時的動作。
963
964不過,大多數自訂設定會延伸 {@link android.preference.DialogPreference} 來顯示對話方塊,以簡化程序。
965延伸 {@link
966android.preference.DialogPreference} 時,您必須在類別建構函式期間呼叫 {@link
967android.preference.DialogPreference#setDialogLayoutResource setDialogLayoutResourcs()},以指定對話方塊的版面配置。
968</p>
969
970  <p>例如,下列為自訂 {@link
971android.preference.DialogPreference} 的建構函式,該偏好設定宣告版面配置並指定預設正值和負值對話方塊按鈕的文字:
972</p>
973
974<pre>
975public class NumberPickerPreference extends DialogPreference {
976    public NumberPickerPreference(Context context, AttributeSet attrs) {
977        super(context, attrs);
978
979        setDialogLayoutResource(R.layout.numberpicker_dialog);
980        setPositiveButtonText(android.R.string.ok);
981        setNegativeButtonText(android.R.string.cancel);
982
983        setDialogIcon(null);
984    }
985    ...
986}
987</pre>
988
989
990
991<h3 id="CustomSave">儲存設定值</h3>
992
993<p>您可以呼叫其中一個 {@link
994android.preference.Preference} 類別的 {@code persist*()} 方法隨時儲存設定值,例如,如果設定值是整數,使用 {@link
995android.preference.Preference#persistInt persistInt()},或者使用 {@link android.preference.Preference#persistBoolean persistBoolean()} 儲存布林值。
996</p>
997
998<p class="note"><strong>注意:</strong>每個 {@link android.preference.Preference} 只能儲存一個資料類型,因此您必須使用適合您自訂 {@link android.preference.Preference} 使用之資料類型的 {@code persist*()} 方法。
999
1000</p>
1001
1002<p>當您選擇保留設定時,可以依據您延伸的 {@link
1003android.preference.Preference} 類別加以設定。如果您延伸 {@link
1004android.preference.DialogPreference},則應該只在對話方塊因正值結果 (使用者選取 [確定] 按鈕) 關閉時保留該值。
1005</p>
1006
1007<p>當 {@link android.preference.DialogPreference} 關閉時,系統會呼叫 {@link
1008android.preference.DialogPreference#onDialogClosed onDialogClosed()} 方法。這個方法包括一個布林值引數,指定使用者結果是否為「正值」&mdash; 如果值為
1009<code>true</code>,則表示使用者選取正值按鈕,而您應該儲存新值。
1010例如:
1011</p>
1012
1013<pre>
1014&#64;Override
1015protected void onDialogClosed(boolean positiveResult) {
1016    // When the user selects "OK", persist the new value
1017    if (positiveResult) {
1018        persistInt(mNewValue);
1019    }
1020}
1021</pre>
1022
1023<p>在此範例中,<code>mNewValue</code> 是保留設定目前值的類別成員。
1024呼叫 {@link android.preference.Preference#persistInt persistInt()} 可將值儲存到 {@link android.content.SharedPreferences} 檔案 (自動使用 XML 檔案中為此 {@link android.preference.Preference} 指定的索引鍵)。
1025
1026</p>
1027
1028
1029<h3 id="CustomInitialize">初始化目前值</h3>
1030
1031<p>當系統將您的 {@link android.preference.Preference} 新增到畫面時,會呼叫 {@link android.preference.Preference#onSetInitialValue onSetInitialValue()} 以通知您設定是否有持續值。
1032
1033如果沒有持續值,這個呼叫會提供您預設值。
1034</p>
1035
1036<p>{@link android.preference.Preference#onSetInitialValue onSetInitialValue()} 方法會傳送布林值 <code>restorePersistedValue</code>,以指出該設定的值是否已經持續。
1037
1038如果是 <code>true</code>,則您應該呼叫其中一個 {@link
1039android.preference.Preference} 類別的 {@code getPersisted*()} 方法以擷取持續值,例如,如果為整數值,可使用 {@link
1040android.preference.Preference#getPersistedInt getPersistedInt()}。
1041您通常都會想要擷取持續值,如此您可以正確的更新 UI 以反映之前儲存的值。
1042
1043</p>
1044
1045<p>如果 <code>restorePersistedValue</code> 是 <code>false</code>,則您應該使用在第二引數中傳送的預設值。
1046</p>
1047
1048<pre>
1049&#64;Override
1050protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) {
1051    if (restorePersistedValue) {
1052        // Restore existing state
1053        mCurrentValue = this.getPersistedInt(DEFAULT_VALUE);
1054    } else {
1055        // Set default state from the XML attribute
1056        mCurrentValue = (Integer) defaultValue;
1057        persistInt(mCurrentValue);
1058    }
1059}
1060</pre>
1061
1062<p>在實際上沒有持續值或沒有索引鍵的情況下,每個 {@code getPersisted*()} 方法會採用指定要使用之預設值的引數。
1063在上述範例中,會使用本機常數來指定預設值,以避免 {@link
1064android.preference.Preference#getPersistedInt getPersistedInt()} 無法傳回持續值。
1065</p>
1066
1067<p class="caution"><strong>注意:</strong>您<strong>無法</strong>使用 <code>defaultValue</code> 作為 {@code getPersisted*()} 方法中的預設值,因為當 <code>restorePersistedValue</code> 為 <code>true</code> 時,其值永遠是 null。
1068
1069</p>
1070
1071
1072<h3 id="CustomDefault">提供預設值</h3>
1073
1074<p>如果 {@link android.preference.Preference} 類別的執行個體指定預設值 (包含 {@code android:defaultValue} 屬性),則系統會在將物件具現化時呼叫 {@link android.preference.Preference#onGetDefaultValue
1075onGetDefaultValue()},以擷取值。
1076
1077您必須實作此方法,才能讓系統將預設值儲存在 {@link
1078android.content.SharedPreferences} 中。
1079例如:</p>
1080
1081<pre>
1082&#64;Override
1083protected Object onGetDefaultValue(TypedArray a, int index) {
1084    return a.getInteger(index, DEFAULT_VALUE);
1085}
1086</pre>
1087
1088<p>方法引數可以提供您所需的所有物件:屬性陣列,以及您必須擷取之 {@code android:defaultValue} 的索引位置。
1089您必須實作此方法以便從屬性擷取預設值的原因,是因為您必須在未定義值的情況為屬性指定一個本機預設值。
1090
1091</p>
1092
1093
1094
1095<h3 id="CustomSaveState">儲存和還原偏好設定狀態</h3>
1096
1097<p>如同版面配置中的 {@link android.view.View},您的 {@link android.preference.Preference} 子類別負責在 Activity 或片段重新啟動 (例如,當使用者旋轉螢幕時) 時,儲存和還原其狀態。
1098
1099如要正確的儲存和還原 {@link android.preference.Preference} 類別的狀態,您必須實作生命週期回呼方法 {@link android.preference.Preference#onSaveInstanceState
1100onSaveInstanceState()} 和 {@link
1101android.preference.Preference#onRestoreInstanceState onRestoreInstanceState()}。
1102
1103</p>
1104
1105<p>您 {@link android.preference.Preference} 的狀態由實作 {@link android.os.Parcelable} 介面的物件定義。
1106Android 架構為您提供這類物件作為定義狀態物件的起始點:{@link
1107android.preference.Preference.BaseSavedState} 類別。
1108</p>
1109
1110<p>如要定義 {@link android.preference.Preference} 類別儲存狀態的方法,您應該延伸 {@link android.preference.Preference.BaseSavedState} 類別。
1111您只需要覆寫幾個方法,然後定義 {@link android.preference.Preference.BaseSavedState#CREATOR}物件。
1112
1113</p>
1114
1115<p>對於大多數應用程式而言,如果您的 {@link android.preference.Preference} 子類別儲存整數以外的資料類型,您可以複製下列實作,然後變更處理 {@code value} 的行即可。
1116
1117</p>
1118
1119<pre>
1120private static class SavedState extends BaseSavedState {
1121    // Member that holds the setting's value
1122    // Change this data type to match the type saved by your Preference
1123    int value;
1124
1125    public SavedState(Parcelable superState) {
1126        super(superState);
1127    }
1128
1129    public SavedState(Parcel source) {
1130        super(source);
1131        // Get the current preference's value
1132        value = source.readInt();  // Change this to read the appropriate data type
1133    }
1134
1135    &#64;Override
1136    public void writeToParcel(Parcel dest, int flags) {
1137        super.writeToParcel(dest, flags);
1138        // Write the preference's value
1139        dest.writeInt(value);  // Change this to write the appropriate data type
1140    }
1141
1142    // Standard creator object using an instance of this class
1143    public static final Parcelable.Creator&lt;SavedState> CREATOR =
1144            new Parcelable.Creator&lt;SavedState>() {
1145
1146        public SavedState createFromParcel(Parcel in) {
1147            return new SavedState(in);
1148        }
1149
1150        public SavedState[] newArray(int size) {
1151            return new SavedState[size];
1152        }
1153    };
1154}
1155</pre>
1156
1157<p>將上述 {@link android.preference.Preference.BaseSavedState} 實作新增到您的應用程式 (通常做為 {@link android.preference.Preference} 子類別的子類別) 之後,您需要針對 {@link android.preference.Preference} 子類別實作 {@link android.preference.Preference#onSaveInstanceState
1158onSaveInstanceState()} 和 {@link
1159android.preference.Preference#onRestoreInstanceState onRestoreInstanceState()} 方法。
1160
1161
1162</p>
1163
1164<p>例如:</p>
1165
1166<pre>
1167&#64;Override
1168protected Parcelable onSaveInstanceState() {
1169    final Parcelable superState = super.onSaveInstanceState();
1170    // Check whether this Preference is persistent (continually saved)
1171    if (isPersistent()) {
1172        // No need to save instance state since it's persistent,
1173        // use superclass state
1174        return superState;
1175    }
1176
1177    // Create instance of custom BaseSavedState
1178    final SavedState myState = new SavedState(superState);
1179    // Set the state's value with the class member that holds current
1180    // setting value
1181    myState.value = mNewValue;
1182    return myState;
1183}
1184
1185&#64;Override
1186protected void onRestoreInstanceState(Parcelable state) {
1187    // Check whether we saved the state in onSaveInstanceState
1188    if (state == null || !state.getClass().equals(SavedState.class)) {
1189        // Didn't save the state, so call superclass
1190        super.onRestoreInstanceState(state);
1191        return;
1192    }
1193
1194    // Cast state to custom BaseSavedState and pass to superclass
1195    SavedState myState = (SavedState) state;
1196    super.onRestoreInstanceState(myState.getSuperState());
1197
1198    // Set this Preference's widget to reflect the restored state
1199    mNumberPicker.setValue(myState.value);
1200}
1201</pre>
1202
1203