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 <CheckBoxPreference>}.</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<PreferenceScreen>}. Внутри этого элемента вы добавляете каждый элемент {@link 197android.preference.Preference}. Каждый дочерний элемент, который вы добавляете внутри элемента 198{@link android.preference.PreferenceScreen <PreferenceScreen>}, отображается в виде одного 199пункта в списке настроек.</p> 200 201<p>Например:</p> 202 203<pre> 204<?xml version="1.0" encoding="utf-8"?> 205<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> 206 <CheckBoxPreference 207 android:key="pref_sync" 208 android:title="@string/pref_sync" 209 android:summary="@string/pref_sync_summ" 210 android:defaultValue="true" /> 211 <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</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 <intent>}</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 <PreferenceCategory>}. <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<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> 288 <PreferenceCategory 289 android:title="@string/pref_sms_storage_title" 290 android:key="pref_key_storage_settings"> 291 <CheckBoxPreference 292 android:key="pref_key_auto_delete" 293 android:summary="@string/pref_summary_auto_delete" 294 android:title="@string/pref_title_auto_delete" 295 android:defaultValue="false"... /> 296 <Preference 297 android:key="pref_key_sms_delete_limit" 298 android:dependency="pref_key_auto_delete" 299 android:summary="@string/pref_summary_delete_limit" 300 android:title="@string/pref_title_sms_delete"... /> 301 <Preference 302 android:key="pref_key_mms_delete_limit" 303 android:dependency="pref_key_auto_delete" 304 android:summary="@string/pref_summary_delete_limit" 305 android:title="@string/pref_title_mms_delete" ... /> 306 </PreferenceCategory> 307 ... 308</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<PreferenceScreen>} 321создает пункт, при выборе которого открывается отдельный список вложенных настроек.</p> 322 323<p>Например:</p> 324 325<pre> 326<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> 327 <!-- opens a subscreen of settings --> 328 <PreferenceScreen 329 android:key="button_voicemail_category_key" 330 android:title="@string/voicemail" 331 android:persistent="false"> 332 <ListPreference 333 android:key="button_voicemail_provider_key" 334 android:title="@string/voicemail_provider" ... /> 335 <!-- opens another nested subscreen --> 336 <PreferenceScreen 337 android:key="button_voicemail_setting_key" 338 android:title="@string/voicemail_settings" 339 android:persistent="false"> 340 ... 341 </PreferenceScreen> 342 <RingtonePreference 343 android:key="button_voicemail_ringtone_key" 344 android:title="@string/voicemail_ringtone_title" 345 android:ringtoneType="notification" ... /> 346 ... 347 </PreferenceScreen> 348 ... 349</PreferenceScreen> 350</pre> 351 352 353<h3 id="Intents">Использование намерений</h3> 354 355<p>В некоторых случаях может потребоваться, чтобы элемент предпочтений открывал другую операцию, а не 356экран настроек, например, веб-браузер для просмотра веб-страницы. Чтобы вызвать {@link 357android.content.Intent}, когда пользователь выбирает элемент предпочтений, добавьте элемент {@code <intent>} 358в качестве дочернего элемента соответствующего элемента {@code <Preference>}.</p> 359 360<p>Например, здесь показано использование элемента предпочтений для открытия веб-страницы:</p> 361 362<pre> 363<Preference android:title="@string/prefs_web_page" > 364 <intent android:action="android.intent.action.VIEW" 365 android:data="http://www.example.com" /> 366</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 @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 @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 @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<!-- default value is a boolean --> 500<CheckBoxPreference 501 android:defaultValue="true" 502 ... /> 503 504<!-- default value is a string --> 505<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 <header>} 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 <header>} 586внутри корневого элемента {@code <preference-headers>}. Например:</p> 587 588<pre> 589<?xml version="1.0" encoding="utf-8"?> 590<preference-headers xmlns:android="http://schemas.android.com/apk/res/android"> 591 <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 <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 <!-- key/value pairs can be included as arguments for the fragment. --> 600 <extra android:name="someKey" android:value="someHeaderValue" /> 601 </header> 602</preference-headers> 603</pre> 604 605<p>Посредством атрибута {@code android:fragment} каждый заголовок объявляет экземпляр фрагмента {@link 606android.preference.PreferenceFragment}, который должен открываться при выборе этого заголовка пользователем.</p> 607 608<p>Элемент {@code <extras>} позволяет передавать пары «ключ-значение» фрагменту в объекте {@link 609android.os.Bundle}. Фрагмент может извлекать аргументы путем вызова метода {@link 610android.app.Fragment#getArguments()}. Вы можете передавать аргументы фрагменту по различным причинам, 611но хорошим поводом является повторное использование одного и того же подкласса {@link 612android.preference.PreferenceFragment} для каждой группы и использование аргументов для указания 613XML-файла предпочтений, который должен быть загружен фрагментом.</p> 614 615<p>Например, здесь приведен фрагмент, который можно использовать повторно для нескольких групп настроек, когда каждый 616заголовок определяет аргумент {@code <extra>} с ключом {@code "settings"}:</p> 617 618<pre> 619public static class SettingsFragment extends PreferenceFragment { 620 @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 @Override 646 public void onBuildHeaders(List<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<Preference>}, которые ведут себя аналогично пунктам заголовка (для использования в более старых версиях 667Android).</p> 668 669<p>Вместо открытия новых экранов {@link android.preference.PreferenceScreen} каждый из элементов {@link 670android.preference.Preference <Preference>} отправляет намерение {@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<preference-headers xmlns:android="http://schemas.android.com/apk/res/android"> 679 <header 680 android:fragment="com.example.prefs.SettingsFragmentOne" 681 android:title="@string/prefs_category_one" 682 android:summary="@string/prefs_summ_category_one" /> 683 <header 684 android:fragment="com.example.prefs.SettingsFragmentTwo" 685 android:title="@string/prefs_category_two" 686 android:summary="@string/prefs_summ_category_two" /> 687</preference-headers> 688</pre> 689 690<p>А здесь представлен файл предпочтений, который содержит те же самые заголовки для версий старше 691Android 3.0 ({@code res/xml/preference_headers_legacy.xml}):</p> 692 693<pre> 694<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> 695 <Preference 696 android:title="@string/prefs_category_one" 697 android:summary="@string/prefs_summ_category_one" > 698 <intent 699 android:targetPackage="com.example.prefs" 700 android:targetClass="com.example.prefs.SettingsActivity" 701 android:action="com.example.prefs.PREFS_ONE" /> 702 </Preference> 703 <Preference 704 android:title="@string/prefs_category_two" 705 android:summary="@string/prefs_summ_category_two" > 706 <intent 707 android:targetPackage="com.example.prefs" 708 android:targetClass="com.example.prefs.SettingsActivity" 709 android:action="com.example.prefs.PREFS_TWO" /> 710 </Preference> 711</PreferenceScreen> 712</pre> 713 714<p>Так как поддержка {@code <preference-headers>} была добавлена в версии 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@Override 725public void onCreate(Bundle savedInstanceState) { 726 super.onCreate(savedInstanceState); 727 ... 728 729 if (Build.VERSION.SDK_INT < 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@Override 737public void onBuildHeaders(List<Header> target) { 738 loadHeadersFromResource(R.xml.preference_headers, target); 739} 740</pre> 741 742<p>Остается обработать намерение {@link android.content.Intent}, переданное 743в операцию, чтобы идентифицировать файл предпочтений для загрузки. Поэтому извлеките операцию намерения и сравните ее 744с известными строками действия, которые вы использовали в тегах {@code <intent>} XML-файла предпочтений:</p> 745 746<pre> 747final static String ACTION_PREFS_ONE = "com.example.prefs.PREFS_ONE"; 748... 749 750@Override 751public void onCreate(Bundle savedInstanceState) { 752 super.onCreate(savedInstanceState); 753 754 String action = getIntent().getAction(); 755 if (action != null && action.equals(ACTION_PREFS_ONE)) { 756 addPreferencesFromResource(R.xml.preferences); 757 } 758 ... 759 760 else if (Build.VERSION.SDK_INT < 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@Override 846protected void onResume() { 847 super.onResume(); 848 getPreferenceScreen().getSharedPreferences() 849 .registerOnSharedPreferenceChangeListener(this); 850} 851 852@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<activity android:name="SettingsActivity" ... > 916 <intent-filter> 917 <action android:name="android.intent.action.MANAGE_NETWORK_USAGE" /> 918 <category android:name="android.intent.category.DEFAULT" /> 919 </intent-filter> 920</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@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@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@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 @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<SavedState> CREATOR = 1144 new Parcelable.Creator<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@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@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