• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1page.title=Настройки
2page.tags=preference,preferenceactivity,preferencefragment
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">Создание операции предпочтений</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>Если вы хотите предоставить настройки для вашего приложения, вы должны использовать
73API-интерфейсы {@link android.preference.Preference} системы Android для построения интерфейса, согласованного с
74привычным для пользователей других приложений Android (включая системные настройки). В этом документе показано,
75как построить настройки вашего приложения посредством API-интерфейсов {@link android.preference.Preference}.</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} для построения пользовательского интерфейса, настройки создаются
94с помощью различных подклассов класса {@link android.preference.Preference}, который вы
95объявляете в XML-файле.</p>
96
97<p>Объект {@link android.preference.Preference} является строительным блоком для отдельной
98настройки. Каждый объект {@link android.preference.Preference} отображается в виде элемента в списке и предоставляет
99соответствующий пользовательский интерфейс для изменения настройки пользователями. Например, {@link
100android.preference.CheckBoxPreference} создает элемент списка, который показывает флажок, а {@link
101android.preference.ListPreference} создает элемент, который открывает диалоговое окно со списком вариантов для выбора.</p>
102
103<p>Каждый добавляемый вами объект {@link android.preference.Preference} имеет соответствующую пару «ключ-значение»,
104которую система использует для сохранения настройки в файле {@link android.content.SharedPreferences}
105значений настроек вашего приложения по умолчанию. Когда пользователь изменяет настройку, система обновляет соответствующее
106значение в файле {@link android.content.SharedPreferences}. Вам потребуется
107напрямую взаимодействовать с файлом, связанным с {@link android.content.SharedPreferences}, только в случае,
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>Поскольку пользовательский интерфейс настроек вашего приложения создается посредством объектов {@link android.preference.Preference},
123а не
124объектов {@link android.view.View}, вам потребуется использовать специализированные подклассы {@link android.app.Activity} или
125{@link android.app.Fragment} для отображения настроек из списка:</p>
126
127<ul>
128  <li>Если ваше приложение поддерживает версии Android старше 3.0 (API уровня 10 и ниже), для построения операции
129необходимо наследовать класс {@link android.preference.PreferenceActivity}.</li>
130  <li>В операционных системах Android 3.0 и более поздних версиях вы должны вместо этого использовать традиционный класс {@link android.app.Activity},
131который содержит объект {@link android.preference.PreferenceFragment} для отображения настроек вашего приложения.
132Однако, когда у вас есть несколько групп настроек, вы можете также
133использовать {@link android.preference.PreferenceActivity} для создания макета с двумя панелями для больших экранов.</li>
134</ul>
135
136<p>Настройка объекта {@link android.preference.PreferenceActivity} и экземпляров {@link
137android.preference.PreferenceFragment} описана в разделах <a href="#Activity">Создание операции предпочтения</a> и <a href="#Fragment">Использование
138фрагментов предпочтений</a>.</p>
139
140
141<h3 id="SettingTypes">Предпочтения</h3>
142
143<p>Каждая настройка для вашего приложения представлена конкретным подклассом класса {@link
144android.preference.Preference}. Каждый подкласс содержит набор основных свойств, которые позволяют вам
145указывать, например, заголовок для настройки и ее значение по умолчанию. Каждый подкласс также содержит
146собственные специализированные свойства и пользовательский интерфейс. В качестве примера на рисунке 1 показан снимок экрана настроек
147приложения Android для обмена сообщениями. Каждый элемент списка на экране настроек возвращается отдельным объектом {@link
148android.preference.Preference}.</p>
149
150<p>Ниже приведены самые распространенные предпочтения:</p>
151
152<dl>
153  <dt>{@link android.preference.CheckBoxPreference}</dt>
154  <dd>Отображает элемент с флажком для настройки, которая может быть включена или выключена. Сохраненное
155значение является логическим (<code>true</code>, если флажок установлен).</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} для выбора числа или даты. Поэтому вам может потребоваться определить
172свой собственный подкласс {@link android.preference.Preference}. См. раздел <a href="#Custom">Построение пользовательского предпочтения</a>.</p>
173
174
175
176<h2 id="DefiningPrefs">Определение предпочтений в XML</h2>
177
178<p>Хотя вы можете создавать новые экземпляры объектов {@link android.preference.Preference} в режиме выполнения, вы должны
179определить список настроек в файле XML с иерархией
180объектов {@link android.preference.Preference}. Использование файла XML для определения вашей коллекции настроек предпочтительней, поскольку файл
181обладает удобочитаемой структурой, которую легко обновлять. Кроме того, настройки вашего приложения
182обычно определены заранее, хотя у вас сохраняется возможность изменять коллекцию в режиме выполнения.</p>
183
184<p>Каждый подкласс класса {@link android.preference.Preference} может быть объявлен посредством элемента XML,
185который соответствует имени класса, например, {@code &lt;CheckBoxPreference&gt;}.</p>
186
187<p>Вы должны сохранить файл XML в каталоге {@code res/xml/}. Хотя вы можете назвать файл любым
188именем, традиционно его называют {@code preferences.xml}. Обычно вам требуется лишь один файл,
189поскольку ветви иерархии (которые открывают собственный список настроек) объявлены с помощью вложенных
190экземпляров {@link android.preference.PreferenceScreen}.</p>
191
192<p class="note"><strong>Примечание.</strong> Если вы хотите создать макет с несколькими панелями для ваших
193настроек, вам потребуются отдельные файлы XML для каждого фрагмента.</p>
194
195<p>Корневой узел XML-файла должен быть элементом {@link android.preference.PreferenceScreen
196&lt;PreferenceScreen&gt;}. Внутри этого элемента вы добавляете каждый элемент {@link
197android.preference.Preference}. Каждый дочерний элемент, который вы добавляете внутри элемента
198{@link android.preference.PreferenceScreen &lt;PreferenceScreen&gt;}, отображается в виде одного
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>Этот атрибут необходим для предпочтений, которые сохраняют значение данных. Он задает уникальный
228ключ (строку), который использует система при сохранении значения этой настройки в {@link
229android.content.SharedPreferences}.
230  <p>Этот атрибут <em>не является обязательным</em> только когда предпочтение представляет собой
231{@link android.preference.PreferenceCategory} или {@link android.preference.PreferenceScreen}, либо
232предпочтение указывает намерение {@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
233android:fragment}</a>).</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> Заголовок
252задан посредством атрибута {@code android:title}.</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>Вы можете пользоваться одним или обоими из этих методов группировки для организации настроек в вашем приложении. Принимая
274решение об используемом варианте и о разделении настроек на группы, вы должны следовать инструкциям в разделе
275<a href="{@docRoot}design/patterns/settings.html">Настройки</a> руководства «Дизайн для Android».</p>
276
277
278<h4 id="Titles">Использование заголовков</h4>
279
280<p>Если вы хотите создать разделители с заголовками между группами настроек (как показано на рисунке 2),
281поместите каждую группу объектов {@link android.preference.Preference} внутри {@link
282android.preference.PreferenceCategory}.</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), поместите каждую группу
315объектов {@link android.preference.Preference} внутри {@link
316android.preference.PreferenceScreen}.</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>В некоторых случаях может потребоваться, чтобы элемент предпочтений открывал другую операцию, а не
356экран настроек, например, веб-браузер для просмотра веб-страницы. Чтобы вызвать {@link
357android.content.Intent}, когда пользователь выбирает элемент предпочтений, добавьте элемент {@code &lt;intent&gt;}
358в качестве дочернего элемента соответствующего элемента {@code &lt;Preference&gt;}.</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>Назначаемое действие, как
374в методе {@link android.content.Intent#setAction setAction()}.</dd>
375  <dt>{@code android:data}</dt>
376    <dd>Назначаемые данные, как в методе {@link android.content.Intent#setData setData()}.</dd>
377  <dt>{@code android:mimeType}</dt>
378    <dd>Назначаемый тип MIME, как
379в методе {@link android.content.Intent#setType setType()}.</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">Создание операции предпочтений</h2>
391
392<p>Для отображения ваших настроек в операции наследуйте класс {@link
393android.preference.PreferenceActivity}. Это наследование традиционного класса {@link
394android.app.Activity}, который отображает список настроек на основе иерархии объектов {@link
395android.preference.Preference}. {@link android.preference.PreferenceActivity}
396автоматически сохраняет настройки, связанные с каждым объектом {@link
397android.preference.Preference}, когда пользователь вносит изменения.</p>
398
399<p class="note"><strong>Примечание.</strong> При разработке приложения для версии Android 3.0
400или выше вместо этого следует использовать {@link android.preference.PreferenceFragment}. Прочитайте следующий раздел
401<a href="#Fragment">Использование фрагментов предпочтений</a>.</p>
402
403<p>Запомните самое важное: не загружайте макет отображаемых объектов во время обратного вызова {@link
404android.preference.PreferenceActivity#onCreate onCreate()}. Вместо этого вызовите {@link
405android.preference.PreferenceActivity#addPreferencesFromResource addPreferencesFromResource()} для
406добавления предпочтений, объявленных в XML-файле для операции. Например, здесь приведен
407 минимальный код, необходимый для работы {@link android.preference.PreferenceActivity}:</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>Этого кода действительно достаточно для некоторых приложений, поскольку как только пользователь изменяет предпочтение,
420система сохраняет изменения в файле {@link android.content.SharedPreferences} по умолчанию, который
421другие компоненты вашего приложения могут читать, когда требуется проверить пользовательские настройки. Однако многим приложениям
422требуется немного больше кода, чтобы отслеживать изменения, происходящие с предпочтениями.
423Информацию об отслеживании изменений в файле {@link android.content.SharedPreferences}
424см. в разделе <a href="#ReadingPrefs">Чтение предпочтений</a>.</p>
425
426
427
428
429<h2 id="Fragment">Использование фрагментов предпочтений</h2>
430
431<p>При разработке приложений для Android 3.0 (API уровня 11) и более поздних версий необходимо использовать {@link
432android.preference.PreferenceFragment} для отображения списка
433объектов {@link android.preference.Preference}. Вы можете добавить {@link android.preference.PreferenceFragment} в любую операцию, при этом
434необязательно использовать {@link android.preference.PreferenceActivity}.</p>
435
436<p><a href="{@docRoot}guide/components/fragments.html">Фрагменты</a> обеспечивают более
437универсальную архитектуру для вашего приложения по сравнению с использованием отдельных операций, вне зависимости от типа
438создаваемой операции. Фактически, для управления отображением ваших настроек мы предлагаем вам использовать {@link
439android.preference.PreferenceFragment} вместо {@link
440android.preference.PreferenceActivity} при каждой возможности.</p>
441
442<p>Ваша реализация {@link android.preference.PreferenceFragment} может содержать просто
443определение метода {@link android.preference.PreferenceFragment#onCreate onCreate()} для загрузки
444файла предпочтений посредством {@link android.preference.PreferenceFragment#addPreferencesFromResource
445addPreferencesFromResource()}. Например:</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} не содержит
478собственного объекта {@link android.content.Context}. Если вам требуется объект {@link android.content.Context},
479вы можете вызвать{@link android.app.Fragment#getActivity()}. Однако разработчик должен быть внимательным и вызывать метод
480{@link android.app.Fragment#getActivity()} только в том случае, когда фрагмент прикреплен к операции. Если
481фрагмент еще не прикреплен или был откреплен в конце его жизненного цикла, метод {@link
482android.app.Fragment#getActivity()} вернет null.</p>
483
484
485<h2 id="Defaults">Установка значений по умолчанию</h2>
486
487<p>Вероятно, создаваемые вами предпочтения определяют важное поведение вашего приложения, поэтому
488необходимо инициализировать соответствующий файл {@link android.content.SharedPreferences},
489записав в него значения по умолчанию для каждого предпочтения {@link android.preference.Preference} при первом запуске вашего
490приложения пользователем.</p>
491
492<p>В первую очередь необходимо указать значение по умолчанию для каждого объекта {@link
493android.preference.Preference}
494в вашем XML-файле посредством атрибута {@code android:defaultValue}. Значение может относиться к любому
495типу данных, подходящему для соответствующего объекта {@link android.preference.Preference}. Например:
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>Затем из метода {@link android.app.Activity#onCreate onCreate()} основной операции вашего приложения
511(и из любой другой операции, через которую пользователь может войти в ваше приложение
512в первый раз) вызовите {@link android.preference.PreferenceManager#setDefaultValues
513setDefaultValues()}:</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-файла предпочтений, для которого вы хотите установить значения по умолчанию.</li>
528  <li>Логическое значение, которое указывает, требуется ли значения по умолчанию устанавливать более одного раза.
529<p>При значении <code>false</code> система устанавливает значения по умолчанию только в том случае, если этот метод никогда не вызывался ранее
530(или атрибут {@link android.preference.PreferenceManager#KEY_HAS_SET_DEFAULT_VALUES}
531в файле общих предпочтений по умолчанию имеет значение false).</p></li>
532</ul>
533
534<p>Когда для третьего аргумента установлено значение <code>false</code>, вы можете вызывать этот метод
535при каждом запуске операции, не опасаясь перезаписи сохраненных пользовательских предпочтений из-за их сброса в состояние
536по умолчанию. Однако, если установить для этого аргумента значение <code>true</code>, вы будете перезаписывать все предыдущие
537значения значениями по умолчанию.</p>
538
539
540
541<h2 id="PreferenceHeaders">Использование заголовков предпочтений</h2>
542
543<p>В редких случаях может потребоваться такая структура настроек, при которой на первом экране отображается только
544список <a href="#Subscreens">подэкранов</a> (например, как в приложении системных настроек,
545показанных на рисунках 4 и 5). При разработке такого дизайна для Android 3.0 и более поздних версий вы должны
546использовать новую возможность Android 3.0 — «заголовки», вместо создания подэкранов посредством вложенных
547элементов {@link android.preference.PreferenceScreen}.</p>
548
549<p>Чтобы создать настройки с заголовками, выполните следующие действия:</p>
550<ol>
551  <li>Выделите каждую группу настроек в отдельный экземпляр {@link
552android.preference.PreferenceFragment}. Таким образом, каждая группа настроек должна иметь отдельный
553XML-файл.</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>Огромное преимущество использования этого дизайна состоит в том, что при запуске на больших экранах {@link android.preference.PreferenceActivity}
563автоматически создает макет с двумя панелями, показанный на рисунке 4.</p>
564
565<p>Даже если ваше приложение поддерживает версии Android старше 3.0, вы можете создать
566приложение, использующее {@link android.preference.PreferenceFragment} для двухпанельного представления на
567новых устройствах и поддерживающее традиционную многоэкранную иерархию на более старых
568устройствах (см. раздел <a href="#BackCompatHeaders">Поддержка старых версий посредством
569заголовков предпочтений</a>).</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> Заголовки
573определяются посредством XML-файла заголовков. <br/><b>2.</b> Каждая группа настроек определяется с помощью фрагмента
574{@link android.preference.PreferenceFragment}, который указывается элементом {@code &lt;header&gt;}
575в файле заголовков.</p>
576
577<img src="{@docRoot}images/ui/settings/settings-headers-handset.png" alt="" />
578<p class="img-caption"><strong>Рисунок 5.</strong> Смартфон с заголовками настроек. При выборе
579пункта вместо заголовков отображается соответствующий
580фрагмент {@link android.preference.PreferenceFragment}.</p>
581
582
583<h3 id="CreateHeaders" style="clear:left">Создание файла заголовков</h3>
584
585<p>Каждая группа настроек в вашем списке заголовков указывается отдельным элементом {@code &lt;header&gt;}
586внутри корневого элемента {@code &lt;preference-headers&gt;}. Например:</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()}. Вы можете передавать аргументы фрагменту по различным причинам,
611но хорошим поводом является повторное использование одного и того же подкласса {@link
612android.preference.PreferenceFragment} для каждой группы и использование аргументов для указания
613XML-файла предпочтений, который должен быть загружен фрагментом.</p>
614
615<p>Например, здесь приведен фрагмент, который можно использовать повторно для нескольких групп настроек, когда каждый
616заголовок определяет аргумент {@code &lt;extra&gt;} с ключом {@code "settings"}:</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()} и вызвать
640{@link android.preference.PreferenceActivity#loadHeadersFromResource
641loadHeadersFromResource()}. Например:</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()}, поскольку единственной обязательной задачей
658операции является загрузка заголовков.</p>
659
660
661<h3 id="BackCompatHeaders">Поддержка старых версий с заголовками предпочтений</h3>
662
663<p>Если ваше приложение поддерживает версии Android старше 3.0, вы можете использовать заголовки для
664предоставления двухпанельного макета при работе на Android 3.0 или более поздней версии. Достаточно создать
665дополнительный XML-файл настроек, использующий базовые элементы {@link android.preference.Preference
666&lt;Preference&gt;}, которые ведут себя аналогично пунктам заголовка (для использования в более старых версиях
667Android).</p>
668
669<p>Вместо открытия новых экранов {@link android.preference.PreferenceScreen} каждый из элементов {@link
670android.preference.Preference &lt;Preference&gt;} отправляет намерение {@link android.content.Intent} в
671{@link android.preference.PreferenceActivity} с указанием XML-файла предпочтений
672для загрузки.</p>
673
674<p>В качестве примера приведен XML-файл для заголовков предпочтений, который используется в Android версии 3.0
675и более поздних версий ({@code res/xml/preference_headers.xml}):</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>А здесь представлен файл предпочтений, который содержит те же самые заголовки для версий старше
691Android 3.0 ({@code res/xml/preference_headers_legacy.xml}):</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>Так как поддержка {@code &lt;preference-headers&gt;} была добавлена в версии Android 3.0, система вызывает
715{@link android.preference.PreferenceActivity#onBuildHeaders onBuildHeaders()} в методе {@link
716android.preference.PreferenceActivity} только при работе в Android версии 3.0 или более поздней версии. Чтобы загрузить
717«старый» файл заголовков ({@code preference_headers_legacy.xml}), вы должны проверить версию Android
718и, если версия старше Android 3.0 ({@link
719android.os.Build.VERSION_CODES#HONEYCOMB}), вызвать {@link
720android.preference.PreferenceActivity#addPreferencesFromResource addPreferencesFromResource()} для
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>Остается обработать намерение {@link android.content.Intent}, переданное
743в операцию, чтобы идентифицировать файл предпочтений для загрузки. Поэтому извлеките операцию намерения и сравните ее
744с известными строками действия, которые вы использовали в тегах {@code &lt;intent&gt;} XML-файла предпочтений:</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()} будут помещать
769все предпочтения в один список, поэтому обязательно используйте операторы else-if, чтобы обеспечить только
770однократный вызов метода при изменении условий.</p>
771
772
773
774
775
776<h2 id="ReadingPrefs">Чтение предпочтений</h2>
777
778<p>По умолчанию все предпочтения вашего приложения сохраняются в файле, который доступен из любого места
779вашего приложения посредством вызова статического метода {@link
780android.preference.PreferenceManager#getDefaultSharedPreferences
781PreferenceManager.getDefaultSharedPreferences()}. Он возвращает объект {@link
782android.content.SharedPreferences}, содержащий все пары «ключ-значение», связанные
783с объектами {@link android.preference.Preference}, использованными в вашей операции {@link
784android.preference.PreferenceActivity}.</p>
785
786<p>В качестве примера показано чтение одного из значений предпочтений из любой другой операции в вашем
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предпочтений. Чтобы получать обратный вызов при изменении любого из предпочтений,
800реализуйте интерфейс {@link android.content.SharedPreferences.OnSharedPreferenceChangeListener
801SharedPreference.OnSharedPreferenceChangeListener} и зарегистрируйте приемник для объекта
802{@link android.content.SharedPreferences} посредством вызова {@link
803android.content.SharedPreferences#registerOnSharedPreferenceChangeListener
804registerOnSharedPreferenceChangeListener()}.</p>
805
806<p>Этот интерфейс содержит только один метод обратного вызова, {@link
807android.content.SharedPreferences.OnSharedPreferenceChangeListener#onSharedPreferenceChanged
808onSharedPreferenceChanged()}, и вы, вероятно, сочтете его самым простым способом реализации интерфейса в составе своей
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>В этом примере метод проверяет, выполнено ли изменение настройки для известного ключа предпочтений. Он
829вызывает {@link android.preference.PreferenceActivity#findPreference findPreference()} для получения объекта
830{@link android.preference.Preference}, который был изменен, поэтому он может изменить сводку пункта
831, описывающего выбор пользователя. То есть, когда настройка представляет собой {@link
832android.preference.ListPreference} или другую настройку с несколькими вариантами выбора, при изменении этой настройки вы должны вызвать {@link
833android.preference.Preference#setSummary setSummary()} для отображения
834текущего состояния (например, настройка спящего режима, показанная на рисунке 5).</p>
835
836<p class="note"><strong>Примечание.</strong> В соответствии с рекомендациями раздела <a href="{@docRoot}design/patterns/settings.html">Настройки</a> руководства «Дизайн для Android», мы рекомендуем вам обновлять
837сводку для {@link android.preference.ListPreference} при каждом изменении предпочтения пользователем,
838чтобы описать текущую настройку.</p>
839
840<p>Для правильного управления жизненным циклом в операции мы рекомендуем вам регистрировать или отменять регистрацию
841вашего приемника {@link android.content.SharedPreferences.OnSharedPreferenceChangeListener} во время выполнения обратных вызовов {@link
842android.app.Activity#onResume} и {@link android.app.Activity#onPause} соответственно:</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>Например, вы можете позволить пользователям управлять частотой синхронизации данных приложения, выполнением загрузки
905только в режиме подключения по Wi-Fi, использованием данных в роуминге и т. д. Когда
906эти возможности управления доступны, пользователи с меньшей вероятностью отключат доступ вашего приложения к данным,
907когда оно достигает установленных в системных настройках лимитов, поскольку вместо отключения они могут
908точно контролировать объем данных, который использует ваше приложение.</p>
909
910<p>После добавления необходимых предпочтений в вашу операцию {@link android.preference.PreferenceActivity}
911для управления поведением вашего приложения в отношении данных вы должны добавить фильтр намерений для {@link
912android.content.Intent#ACTION_MANAGE_NETWORK_USAGE} в вашем файле манифеста. Например:</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>Этот фильтр манифеста указывает системе, что эта операция управляет использованием
924данных вашим приложением. Так, когда пользователь проверяет объем использованных приложением данных в системном приложении
925«Настройки», отображается кнопка <em>Просмотреть настройки приложения</em>, которая запускает вашу операцию
926{@link android.preference.PreferenceActivity}, чтобы пользователь мог уточнить, сколько данных использует
927ваше приложение.</p>
928
929
930
931
932
933
934
935<h2 id="Custom">Построение пользовательского предпочтения</h2>
936
937<p>Система Android содержит множество подклассов {@link android.preference.Preference}, которые
938позволяют вам строить пользовательский интерфейс для нескольких различных типов настроек.
939Тем не менее, вы можете обнаружить, что для нужной вам настройки нет встроенного решения, например, для выбора
940числа или даты. В таком случае вам потребуется создать нестандартное предпочтение путем наследования
941класса {@link android.preference.Preference} или одного из других подклассов.</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} содержит свой собственный пользовательский интерфейс (например, диалоговое окно), сохраните
953и восстановите состояние для обработки изменений жизненного цикла (например, когда пользователь поворачивает экран).</li>
954</ul>
955
956<p>В следующих разделах описано выполнение каждой из этих задач.</p>
957
958
959
960<h3 id="CustomSelected">Указание пользовательского интерфейса</h3>
961
962  <p>Если вы наследуете класс {@link android.preference.Preference} непосредственно, вы должны реализовать метод
963{@link android.preference.Preference#onClick()}, чтобы задать действие, происходящее при выборе
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>Вы можете сохранить значение настройки в любой момент, вызвав один из методов {@code persist*()} класса {@link
994android.preference.Preference}, например, {@link
995android.preference.Preference#persistInt persistInt()}, если настройка имеет целое значение, или
996{@link android.preference.Preference#persistBoolean persistBoolean()} для сохранения логического значения.</p>
997
998<p class="note"><strong>Примечание.</strong> Каждое предпочтение {@link android.preference.Preference} может сохранять только один
999тип данных, поэтому вы должны использовать метод {@code persist*()}, соответствующий типу данных, используемых вашим
1000пользовательским предпочтением {@link android.preference.Preference}.</p>
1001
1002<p>Выбор метода сохранения настройки может зависеть от наследованного класса {@link
1003android.preference.Preference}. Если вы наследуете {@link
1004android.preference.DialogPreference}, вы должны сохранять значение только при закрытии диалога
1005с положительным результатом (пользователь нажал кнопку «OK»).</p>
1006
1007<p>Когда {@link android.preference.DialogPreference} закрывается, система вызывает метод {@link
1008android.preference.DialogPreference#onDialogClosed onDialogClosed()}. Этот метод содержит
1009логический аргумент, который указывает, является ли результат пользователя «положительным» — если аргумент имеет значение
1010<code>true</code>, значит пользователь выбрал положительную кнопку и вы должны сохранить новое значение. Например:
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()} значение сохраняется
1025в файл {@link android.content.SharedPreferences} (с автоматическим использованием ключа,
1026указанного в XML-файле для этого предпочтения {@link android.preference.Preference}).</p>
1027
1028
1029<h3 id="CustomInitialize">Инициализация текущего значения</h3>
1030
1031<p>Когда система добавляет ваше предпочтение {@link android.preference.Preference} на экран, она
1032вызывает метод {@link android.preference.Preference#onSetInitialValue onSetInitialValue()}, чтобы уведомить вас,
1033имеет ли настройка сохраненное значение. Если сохраненного значения нет, этот вызов предоставляет вам
1034значение по умолчанию.</p>
1035
1036<p>Метод {@link android.preference.Preference#onSetInitialValue onSetInitialValue()} передает
1037логическое значение, <code>restorePersistedValue</code>, чтобы показать, было ли уже сохранено значение
1038для настройки. Если значение равно <code>true</code>, вы должны извлечь сохраненное значение, вызвав
1039один из методов {@code getPersisted*()} класса {@link
1040android.preference.Preference}, например, {@link
1041android.preference.Preference#getPersistedInt getPersistedInt()} для целого значения. Обычно
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значение по умолчанию на случай, когда действительно нет сохраненного значения, или не существует ключ. В
1064приведенном выше примере локальная константа служит для указания значения по умолчанию на случай, если {@link
1065android.preference.Preference#getPersistedInt getPersistedInt()} не может вернуть сохраненное значение.</p>
1066
1067<p class="caution"><strong>Внимание!</strong> Вы <strong>не можете</strong> использовать
1068<code>defaultValue</code> в качестве значения по умолчанию в методе {@code getPersisted*()}, так как
1069его значение всегда равно null, когда <code>restorePersistedValue</code> имеет значение <code>true</code>.</p>
1070
1071
1072<h3 id="CustomDefault">Предоставление значения по умолчанию</h3>
1073
1074<p>Если экземпляр вашего класса {@link android.preference.Preference} указывает значение по умолчанию
1075(с помощью атрибута {@code android:defaultValue}),
1076система вызывает {@link android.preference.Preference#onGetDefaultValue
1077onGetDefaultValue()}, когда она создает экземпляр объекта для извлечения значения. Вы должны реализовать
1078этот метод, чтобы сохранить значение по умолчанию для системы в {@link
1079android.content.SharedPreferences}. Например:</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>Аргументы метода предоставляют все необходимое: массив атрибутов и указатель
1089положения {@code android:defaultValue}, который вы должны извлечь. Причина, по которой вы должны
1090реализовать этот метод, чтобы извлечь значение по умолчанию из атрибута, состоит в том, что вы должны указать
1091локальное значение по умолчанию для атрибута в случае, когда значение не определено.</p>
1092
1093
1094
1095<h3 id="CustomSaveState">Сохранение и восстановление состояния предпочтений</h3>
1096
1097<p>Как и {@link android.view.View} в макете, ваш подкласс {@link android.preference.Preference}
1098отвечает за сохранение и восстановление своего состояния в случае перезапуска операции или фрагмента
1099(например, когда пользователь поворачивает экран). Чтобы правильно сохранять и восстанавливать
1100состояние вашего класса {@link android.preference.Preference}, вы должны реализовать
1101методы обратного вызова жизненного цикла {@link android.preference.Preference#onSaveInstanceState
1102onSaveInstanceState()} и {@link
1103android.preference.Preference#onRestoreInstanceState onRestoreInstanceState()}.</p>
1104
1105<p>Состояние вашего {@link android.preference.Preference} определяется объектом, который реализует
1106интерфейс {@link android.os.Parcelable}. Система Android предоставляет вам такой объект
1107в качестве начальной точки для определения вашего объекта состояния: класс {@link
1108android.preference.Preference.BaseSavedState}.</p>
1109
1110<p>Чтобы определить, как ваш класс {@link android.preference.Preference} сохраняет свое состояние, вы должны
1111наследовать класс {@link android.preference.Preference.BaseSavedState}. Вы должны переопределить лишь
1112 несколько методов и определить объект
1113{@link android.preference.Preference.BaseSavedState#CREATOR}.</p>
1114
1115<p>Для большинства приложений вы можете скопировать следующую реализацию и просто изменить строки, которые
1116обрабатывают {@code value}, если ваш подкласс {@link android.preference.Preference} сохраняет типы
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}
1158в ваше приложение (обычно в качестве подкласса вашего подкласса {@link android.preference.Preference}), вам
1159потребуется реализовать методы {@link android.preference.Preference#onSaveInstanceState
1160onSaveInstanceState()} и {@link
1161android.preference.Preference#onRestoreInstanceState onRestoreInstanceState()} для вашего
1162подкласса {@link android.preference.Preference}.</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