1page.title=Configurações 2page.tags=preferência,preferenceactivity,preferencefragment 3 4@jd:body 5 6 7<div id="qv-wrapper"> 8<div id="qv"> 9 10<h2>Neste documento</h2> 11<ol> 12 <li><a href="#Overview">Visão geral</a> 13 <ol> 14 <li><a href="#SettingTypes">Preferências</a></li> 15 </ol> 16 </li> 17 <li><a href="#DefiningPrefs">Definição de preferências em XML</a> 18 <ol> 19 <li><a href="#Groups">Criação de grupos de configuração</a></li> 20 <li><a href="#Intents">Uso de intenções</a></li> 21 </ol> 22 </li> 23 <li><a href="#Activity">Criação de uma atividade de preferência</a></li> 24 <li><a href="#Fragment">Uso de fragmentos de preferência</a></li> 25 <li><a href="#Defaults">Configuração de valores padrão</a></li> 26 <li><a href="#PreferenceHeaders">Uso de cabeçalhos de preferência</a> 27 <ol> 28 <li><a href="#CreateHeaders">Criação do arquivo de cabeçalhos</a></li> 29 <li><a href="#DisplayHeaders">Exibição de cabeçalhos</a></li> 30 <li><a href="#BackCompatHeaders">Compatibilidade de versões mais antigas com cabeçalhos de preferência</a></li> 31 </ol> 32 </li> 33 <li><a href="#ReadingPrefs">Leitura de preferências</a> 34 <ol> 35 <li><a href="#Listening">Escuta de alterações de preferência</a></li> 36 </ol> 37 </li> 38 <li><a href="#NetworkUsage">Gerenciamento de uso de rede</a></li> 39 <li><a href="#Custom">Composição de uma preferência personalizada</a> 40 <ol> 41 <li><a href="#CustomSelected">Especificação da interface do usuário</a></li> 42 <li><a href="#CustomSave">Salvamento do valor da configuração</a></li> 43 <li><a href="#CustomInitialize">Inicialização do valor atual</a></li> 44 <li><a href="#CustomDefault">Fornecimento de um valor padrão</a></li> 45 <li><a href="#CustomSaveState">Salvamento e restauração do estado da preferência</a></li> 46 </ol> 47 </li> 48</ol> 49 50<h2>Classes principais</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>Veja também</h2> 59<ol> 60 <li><a href="{@docRoot}design/patterns/settings.html">Guia de projeto de configurações</a></li> 61</ol> 62</div> 63</div> 64 65 66 67 68<p>Geralmente os aplicativos contêm configurações que permitem aos usuários modificar características e comportamentos do aplicativo. Por 69exemplo: alguns aplicativos permitem aos usuários especificar se as notificações estão ativadas ou especificar a frequência 70com que o aplicativo sincroniza dados com a nuvem.</p> 71 72<p>Para fornecer configurações ao aplicativo, é preciso usar 73as APIs {@link android.preference.Preference} do Android para programar uma interface coerente 74com a experiência do usuário em outros aplicativos Android (inclusive as configurações do sistema). Este documento descreve 75como programar as configurações do aplicativo por meio de APIs {@link android.preference.Preference}.</p> 76 77<div class="note design"> 78<p><strong>Projeto de configurações</strong></p> 79 <p>Para obter mais informações sobre o projeto de configurações, leia o guia de projeto <a href="{@docRoot}design/patterns/settings.html">Configurações</a>.</p> 80</div> 81 82 83<img src="{@docRoot}images/ui/settings/settings.png" alt="" width="435" /> 84<p class="img-caption"><strong>Figura 1.</strong> Capturas de tela das configurações do aplicativo Mensagens 85do Android. A seleção de um item definido por uma {@link android.preference.Preference} 86abre uma interface para alterar a configuração.</p> 87 88 89 90 91<h2 id="Overview">Visão geral</h2> 92 93<p>Em vez de usar objetos {@link android.view.View} para criar a interface do usuário, as configurações 94são criadas por meio de várias subclasses da classe {@link android.preference.Preference} 95declaradas em um arquivo XML.</p> 96 97<p>Os objetos {@link android.preference.Preference} são as peças fundamentais de uma única 98configuração. Cada {@link android.preference.Preference} aparece como um item em uma lista e oferece a IU 99adequada para que os usuários modifiquem a configuração. Por exemplo: uma {@link 100android.preference.CheckBoxPreference} cria um item de lista que exibe uma caixa de seleção e uma {@link 101android.preference.ListPreference} cria um item que abre uma caixa de diálogo com uma lista de opções.</p> 102 103<p>Cada {@link android.preference.Preference} adicionada tem um par de valor-chave correspondente 104que o sistema usa para salvar a configuração em um arquivo 105{@link android.content.SharedPreferences} padrão para as configurações do aplicativo. Quando o usuário altera uma configuração, o sistema atualiza o valor 106correspondente no arquivo {@link android.content.SharedPreferences}. O único momento em que 107se deve interagir diretamente com o arquivo {@link android.content.SharedPreferences} associado 108é no momento de ler o valor para determinar o comportamento do aplicativo com base na configuração do usuário.</p> 109 110<p>O valor salvo em {@link android.content.SharedPreferences} para cada configuração pode ser 111um dos seguintes tipos de dados:</p> 112 113<ul> 114 <li>Boolean</li> 115 <li>Float</li> 116 <li>Int</li> 117 <li>Long</li> 118 <li>String</li> 119 <li>String {@link java.util.Set}</li> 120</ul> 121 122<p>Como a IU de configurações do aplicativo é criada com objetos {@link android.preference.Preference} 123 em vez de objetos 124{@link android.view.View}, é preciso usar uma subclasse {@link android.app.Activity} ou 125{@link android.app.Fragment} especializada para exibir as configurações de lista:</p> 126 127<ul> 128 <li>Se o aplicativo for compatível com versões do Android anteriores à 3.0 (nível da API 10 ou anterior), será 129necessário criar a atividade como uma extensão da classe {@link android.preference.PreferenceActivity}.</li> 130 <li>No Android 3.0 ou versões posteriores, deve-se usar um {@link android.app.Activity} tradicional 131que hospeda um {@link android.preference.PreferenceFragment} que exige as configurações do aplicativo. 132No entanto, pode-se também usar {@link android.preference.PreferenceActivity} para criar um layout de dois painéis 133para telas maiores quando há vários grupos de configurações.</li> 134</ul> 135 136<p>Veja como configurar a {@link android.preference.PreferenceActivity} e instâncias de {@link 137android.preference.PreferenceFragment} nas seções sobre a <a href="#Activity">Criação de uma atividade de preferência</a> e <a href="#Fragment">Uso 138de fragmentos de preferência</a>.</p> 139 140 141<h3 id="SettingTypes">Preferências</h3> 142 143<p>Toda configuração do aplicativo é representada por uma subclasse específica da classe {@link 144android.preference.Preference}. Cada subclasse contém um conjunto de propriedades essenciais que permitem 145especificar itens como o título da configuração e o valor padrão. Cada subclasse também oferece 146suas propriedades e interface do usuário especializadas. Por exemplo: a figura 1 ilustra uma captura de tela 147das configurações do aplicativo Mensagens. Cada item de lista na tela de configurações tem, como fundo, um objeto {@link 148android.preference.Preference} diferente.</p> 149 150<p>A seguir há algumas das preferências mais comuns:</p> 151 152<dl> 153 <dt>{@link android.preference.CheckBoxPreference}</dt> 154 <dd>Exibe um item com uma caixa de seleção para uma configuração que esteja ativada ou desativada. O valor 155salvo é um booleano (<code>true</code> se estiver selecionada).</dd> 156 157 <dt>{@link android.preference.ListPreference}</dt> 158 <dd>Abre uma caixa de diálogo com uma lista de botões de opção. O valor salvo 159pode ser qualquer um dos tipos de valor compatíveis (listados acima).</dd> 160 161 <dt>{@link android.preference.EditTextPreference}</dt> 162 <dd>Abre uma caixa de diálogo com um widget {@link android.widget.EditText}. O valor salvo é um {@link 163java.lang.String}.</dd> 164</dl> 165 166<p>Consulte a classe {@link android.preference.Preference} para ver uma lista de todas as outras subclasses e 167as propriedades correspondentes.</p> 168 169<p>É claro que as classes embutidas não acomodam todas as necessidades e o aplicativo pode exigir 170algo mais especializado. Por exemplo: a plataforma atualmente não fornece nenhuma classe {@link 171android.preference.Preference} para selecionar um número ou data. Portanto, pode ser necessário definir 172a própria subclasse {@link android.preference.Preference}. Veja mais informações na seção sobre <a href="#Custom">Composição de uma preferência personalizada</a>.</p> 173 174 175 176<h2 id="DefiningPrefs">Definição de preferências em XML</h2> 177 178<p>Embora se possa instanciar novos objetos {@link android.preference.Preference} em tempo de execução, 179deve-se definir uma lista de configurações no XML com uma hierarquia 180de objetos {@link android.preference.Preference}. Recomenda-se o uso de um arquivo XML para definir a coleção de configurações porque o arquivo 181oferece uma estrutura fácil de ler e simples de atualizar. Além disso, as configurações do aplicativo 182geralmente são predeterminadas, embora ainda seja possível modificar a coleção em tempo de execução.</p> 183 184<p>Cada subclasse {@link android.preference.Preference} pode ser declarada com um elemento XML 185correspondente ao nome da classe, como {@code <CheckBoxPreference>}.</p> 186 187<p>É preciso salvar o arquivo XML no diretório {@code res/xml/}. Embora seja possível nomear livremente 188o arquivo, é mais frequente vê-lo com o nome {@code preferences.xml}. Geralmente só é necessário um arquivo 189porque as ramificações na hierarquia (que abrem sua própria lista de configurações) são declaradas 190por meio de instâncias aninhadas de {@link android.preference.PreferenceScreen}.</p> 191 192<p class="note"><strong>Observação:</strong> se você deseja criar um layout de vários painéis 193para as configurações, serão necessários arquivos XML separados para cada fragmento.</p> 194 195<p>O nó raiz do arquivo XML deve ser um elemento {@link android.preference.PreferenceScreen 196<PreferenceScreen>}. É dentro desse elemento que se adiciona cada {@link 197android.preference.Preference}. Cada filho adicionado dentro do elemento 198{@link android.preference.PreferenceScreen <PreferenceScreen>} é exibido com um item 199único na lista de configurações.</p> 200 201<p>Por exemplo:</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>Nesse exemplo, existe um {@link android.preference.CheckBoxPreference} e um {@link 223android.preference.ListPreference}. Os dois itens contêm estes três atributos:</p> 224 225<dl> 226 <dt>{@code android:key}</dt> 227 <dd>Esse atributo é necessário para preferências que persistem a um valor de dados. Ele especifica a chave 228exclusiva (uma string) que o sistema usa ao salvar o valor dessa configuração em {@link 229android.content.SharedPreferences}. 230 <p>As únicas instâncias em que esse atributo é <em>dispensável</em> ocorrem quando a preferência é um 231{@link android.preference.PreferenceCategory} ou {@link android.preference.PreferenceScreen}, 232ou quando a preferência especifica um {@link android.content.Intent} para invocar (com um elemento <a href="#Intents">{@code <intent>}</a>) ou um {@link android.app.Fragment} para exibir (com um atributo <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>Fornece à configuração um nome visível ao usuário.</dd> 237 <dt>{@code android:defaultValue}</dt> 238 <dd>Especifica o valor inicial que o sistema deve definir no arquivo {@link 239android.content.SharedPreferences}. Deve-se fornecer um valor padrão para 240todas as configurações.</dd> 241</dl> 242 243<p>Para mais informações sobre todos os outros atributos compatíveis, consulte a documentação {@link 244android.preference.Preference} (e subclasse respectiva).</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>Figura 2.</strong> Definição de categorias 250com títulos. <br/><b>1.</b> A categoria é especificada pelo elemento {@link 251android.preference.PreferenceCategory <PreferenceCategory>}. <br/><b>2.</b> O título 252é especificado com o atributo {@code android:title}.</p> 253</div> 254 255 256<p>Quando a lista de configurações excede cerca de 10 itens, pode ser necessário adicionar títulos 257para definir grupos de configurações ou exibir esses grupos 258em uma tela separada. Essas opções são descritas nas seções a seguir.</p> 259 260 261<h3 id="Groups">Criação de grupos de configuração</h3> 262 263<p>Se você apresentar uma lista de 10 ou mais configurações, 264os usuários podem ter dificuldade de percorrê-las, compreendê-las e processá-las. Para solucionar isso, 265pode-se dividir algumas ou todas as configurações em grupos, transformando uma longa lista 266em várias listas mais curtas. Um grupo de configurações relacionadas pode ser apresentado de uma das seguintes formas:</p> 267 268<ul> 269 <li><a href="#Titles">Uso de títulos</a></li> 270 <li><a href="#Subscreens">Uso de subtelas</a></li> 271</ul> 272 273<p>Pode-se usar uma ou ambas as técnicas de agrupamento para organizar as configurações do aplicativo. Ao decidir 274qual delas usar e como dividir as configurações, deve-se seguir as diretrizes do guia 275<a href="{@docRoot}design/patterns/settings.html">Configurações</a> de Projeto do Android.</p> 276 277 278<h4 id="Titles">Uso de títulos</h4> 279 280<p>Para usar divisores com cabeçalhos entre grupos de configurações (como ilustrado na figura 2), 281coloca-se cada grupo de objetos {@link android.preference.Preference} dentro de {@link 282android.preference.PreferenceCategory}.</p> 283 284<p>Por exemplo:</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">Uso de subtelas</h4> 313 314<p>Para usar grupos de configurações em uma subtela (como ilustrado na figura 3), coloque o grupo 315de objetos {@link android.preference.Preference} dentro de {@link 316android.preference.PreferenceScreen}.</p> 317 318<img src="{@docRoot}images/ui/settings/settings-subscreen.png" alt="" /> 319<p class="img-caption"><strong>Figura 3.</strong> Subtelas de configuração. O elemento {@code 320<PreferenceScreen>} cria 321um item que, quando selecionado, abre uma lista separada para exibir as configurações aninhadas.</p> 322 323<p>Por exemplo:</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">Uso de intenções</h3> 354 355<p>Em alguns casos, pode ser necessário que um item de preferência abra em um atividade diferente 356e não na tela de configuração, como um navegador da web para exibir uma página da web. Para invocar um {@link 357android.content.Intent} quando o usuário seleciona um item de preferência, adicione um elemento {@code <intent>} 358como filho do elemento {@code <Preference>} correspondente.</p> 359 360<p>Por exemplo, a seguir apresenta-se como usar um item de preferência para abrir uma página da web:</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>É possível criar intenções implícitas e explícitas usando os seguintes atributos:</p> 370 371<dl> 372 <dt>{@code android:action}</dt> 373 <dd>A ação a atribuir, conforme o método {@link android.content.Intent#setAction setAction()}. 374</dd> 375 <dt>{@code android:data}</dt> 376 <dd>Os dados a atribuir, conforme o método {@link android.content.Intent#setData setData()}.</dd> 377 <dt>{@code android:mimeType}</dt> 378 <dd>O tipo MIME atribuir, conforme o método {@link android.content.Intent#setType setType()}. 379</dd> 380 <dt>{@code android:targetClass}</dt> 381 <dd>A parte de classe do nome do componente, conforme o método {@link android.content.Intent#setComponent 382setComponent()}.</dd> 383 <dt>{@code android:targetPackage}</dt> 384 <dd>A parte de pacote do nome do componente, conforme o método {@link 385android.content.Intent#setComponent setComponent()}.</dd> 386</dl> 387 388 389 390<h2 id="Activity">Criação de uma atividade de preferência</h2> 391 392<p>Para exibir as configurações em uma atividade, estenda a classe {@link 393android.preference.PreferenceActivity}. É uma extensão da classe tradicional {@link 394android.app.Activity} que exibe uma lista de configurações com base em uma hierarquia de objetos {@link 395android.preference.Preference}. A {@link android.preference.PreferenceActivity} 396automaticamente persiste às configurações associadas a cada {@link 397android.preference.Preference} quando o usuário faz uma alteração.</p> 398 399<p class="note"><strong>Observação:</strong> ao desenvolver um aplicativo para Android 3.0 400ou superior, deve-se usar o {@link android.preference.PreferenceFragment}. Consulte a próxima 401seção sobre o <a href="#Fragment">Uso de fragmentos de preferência</a>.</p> 402 403<p>O mais importante é não carregar um layout de vistas durante o retorno de chamada {@link 404android.preference.PreferenceActivity#onCreate onCreate()}. Em vez disso, chama-se {@link 405android.preference.PreferenceActivity#addPreferencesFromResource addPreferencesFromResource()} 406para adicionar à atividade as preferências declaradas em um arquivo XML. Por exemplo: abaixo há o código mínimo 407necessário para um {@link android.preference.PreferenceActivity} funcional:</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>Na verdade, esse código é suficiente para alguns aplicativos porque, assim que o usuário modifica uma preferência, 420o sistema salva as alterações em um arquivo padrão {@link android.content.SharedPreferences} 421que os componentes do outro aplicativo poderá ler quando for necessário verificar as configurações do usuário. No entanto, 422muitos aplicativos exigem um pouco mais de código para escutar as alterações que ocorrem nas preferências. 423Para informações sobre a escuda de alterações no arquivo {@link android.content.SharedPreferences}, 424consulte a seção sobre <a href="#ReadingPrefs">Leitura de preferências</a>.</p> 425 426 427 428 429<h2 id="Fragment">Uso de fragmentos de preferência</h2> 430 431<p>Ao desenvolver para Android 3.0 (nível da API 11) ou versões posteriores, deve-se usar um {@link 432android.preference.PreferenceFragment} para exibir a lista de objetos {@link android.preference.Preference}. 433 Pode-se adicionar um {@link android.preference.PreferenceFragment} a qualquer atividade — não é 434necessário usar {@link android.preference.PreferenceActivity}.</p> 435 436<p>Os <a href="{@docRoot}guide/components/fragments.html">fragmentos</a> permitem uma arquitetura 437mais flexível para o aplicativo em comparação com o uso de apenas atividades para qualquer 438tipo de atividade criada. Assim, sugerimos usar {@link 439android.preference.PreferenceFragment} para controlar a exibição das configurações em vez de {@link 440android.preference.PreferenceActivity} sempre que possível.</p> 441 442<p>A implementação de {@link android.preference.PreferenceFragment} pode ser tão simples 443quanto definir o método {@link android.preference.PreferenceFragment#onCreate onCreate()} para carregar 444um arquivo de preferências com {@link android.preference.PreferenceFragment#addPreferencesFromResource 445addPreferencesFromResource()}. Por exemplo:</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>É possível adicionar esse fragmento a um {@link android.app.Activity} como se faria com qualquer outro 461{@link android.app.Fragment}. Por exemplo:</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>Observação:</strong> um {@link android.preference.PreferenceFragment} não tem 478seu próprio objeto {@link android.content.Context}. Se for necessário um objeto {@link android.content.Context} 479, é possível chamar {@link android.app.Fragment#getActivity()}. No entanto, tome cuidado para chamar 480{@link android.app.Fragment#getActivity()} somente quando o fragmento estiver anexado a uma atividade. Quando 481o fragmento ainda não estiver anexado, ou tiver sido separado durante o fim do seu ciclo de vida, {@link 482android.app.Fragment#getActivity()} retornará como nulo.</p> 483 484 485<h2 id="Defaults">Configuração de valores padrão</h2> 486 487<p>As preferências criadas provavelmente definem alguns comportamentos importantes do aplicativo, portanto 488é necessário inicializar o arquivo {@link android.content.SharedPreferences} associado 489com os valores padrão de cada {@link android.preference.Preference} quando o usuário abre o aplicativo 490pela primeira vez.</p> 491 492<p>A primeira coisa a fazer é especificar o valor padrão de cada objeto {@link 493android.preference.Preference} 494no arquivo XML com o atributo {@code android:defaultValue}. O valor pode ser qualquer tipo de dados 495apropriado para o objeto {@link android.preference.Preference} correspondente. Por 496exemplo:</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>Em seguida, a partir do método {@link android.app.Activity#onCreate onCreate()} na atividade principal 511do aplicativo — e em qualquer outra atividade pela qual o usuário possa entrar no aplicativo pela 512primeira vez —, chame {@link android.preference.PreferenceManager#setDefaultValues 513setDefaultValues()}:</p> 514 515<pre> 516PreferenceManager.setDefaultValues(this, R.xml.advanced_preferences, false); 517</pre> 518 519<p>Essa chamada durante {@link android.app.Activity#onCreate onCreate()} garante que o aplicativo 520seja adequadamente inicializado com as configurações padrão, que o aplicativo pode precisar ler 521para determinar alguns comportamentos (se, por exemplo, baixará dados enquanto estiver 522em uma rede de celular).</p> 523 524<p>Esse método usa três argumentos:</p> 525<ul> 526 <li>O {@link android.content.Context} do aplicativo.</li> 527 <li>O ID de recurso do arquivo XML de preferências para o qual você deseja definir os valores padrão.</li> 528 <li>Booleano que indica se os valores padrão devem ser definidos mais de uma vez. 529<p>Quando <code>false</code>, o sistema define os valores parão somente se esse método nunca tiver 530sido chamado (ou se {@link android.preference.PreferenceManager#KEY_HAS_SET_DEFAULT_VALUES} 531no arquivo de preferências compartilhadas do valor padrão for falso).</p></li> 532</ul> 533 534<p>Enquanto o terceiro argumento estiver definido como <code>false</code>, pode-se chamar esse método com segurança 535toda vez que a atividade iniciar sem substituir as preferências salvas do usuário redefinindo-as 536para os padrões. No entanto, se ele for definido como <code>true</code>, todos os valores anteriores 537serão substituídos pelos padrões.</p> 538 539 540 541<h2 id="PreferenceHeaders">Uso de cabeçalhos de preferência</h2> 542 543<p>Em casos raros, pode ser necessário projetar as configurações de forma que a primeira tela 544exiba somente uma lista de <a href="#Subscreens">subtelas</a> (como as do aplicativo Configurações 545conforme ilustrado nas figuras 4 e 5). Ao desenvolver um projeto desse tipo para Android 3.0 ou versão posterior, 546deve-se usar um novo recurso "cabeçalhos" no Android 3.0 em vez de criar subtelas com elementos 547{@link android.preference.PreferenceScreen} aninhados.</p> 548 549<p>Para criar as configurações com cabeçalhos, é preciso:</p> 550<ol> 551 <li>Separar cada grupo de configurações em instâncias separadas de {@link 552android.preference.PreferenceFragment}. Ou seja, cada grupo de configurações precisa de um arquivo 553XML separado.</li> 554 <li>Criar um arquivo XML de cabeçalhos que lista cada grupo de configurações e declara que fragmento 555contém a lista correspondente de configurações.</li> 556 <li>Estender a classe {@link android.preference.PreferenceActivity} para hospedar as configurações.</li> 557 <li>Implementar o retorno de chamada {@link 558android.preference.PreferenceActivity#onBuildHeaders onBuildHeaders()} para especificar 559o arquivo de cabeçalhos.</li> 560</ol> 561 562<p>Um grande benefício de usar esse modelo é que {@link android.preference.PreferenceActivity} 563automaticamente apresenta o layout de dois painéis ilustrado na figura 4 ao executar em telas grandes.</p> 564 565<p>Mesmo se o aplicativo for compatível com versões de Android anteriores à 3.0, é possível programar 566o aplicativo para usar {@link android.preference.PreferenceFragment} para uma apresentação em dois painéis 567em dispositivos mais novos e ser compatível com a hierarquia tradicional multitelas 568em dispositivos mais antigos (veja a seção sobre <a href="#BackCompatHeaders">Compatibilidade de versões 569mais antigas com cabeçalhos de preferência</a>).</p> 570 571<img src="{@docRoot}images/ui/settings/settings-headers-tablet.png" alt="" /> 572<p class="img-caption"><strong>Figura 4.</strong> Layout de dois painéis com cabeçalhos. <br/><b>1.</b> Os cabeçalhos 573são definidos com um arquivo XML de cabeçalhos. <br/><b>2.</b> Cada grupo de configurações é definido por um 574{@link android.preference.PreferenceFragment} especificado por um elemento {@code <header>} 575no arquivo de cabeçalhos.</p> 576 577<img src="{@docRoot}images/ui/settings/settings-headers-handset.png" alt="" /> 578<p class="img-caption"><strong>Figura 5.</strong> Um dispositivo celular com cabeçalhos de configuração. Quando 579um item é selecionado o {@link android.preference.PreferenceFragment} associado substitui 580os cabeçalhos.</p> 581 582 583<h3 id="CreateHeaders" style="clear:left">Criação do arquivo de cabeçalhos</h3> 584 585<p>Cada grupo de configurações na lista de cabeçalhos é especificado por um único elemento {@code <header>} 586dentro de um elemento raiz {@code <preference-headers>}. Por exemplo:</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>Com o atributo {@code android:fragment}, cada cabeçalho declara uma instância de {@link 606android.preference.PreferenceFragment} que deve abrir quando o usuário selecionar o cabeçalho.</p> 607 608<p>O elemento {@code <extras>} permite passar os pares de valores-chave para o fragmento em um {@link 609android.os.Bundle}. O fragmento pode recuperar os argumentos chamando {@link 610android.app.Fragment#getArguments()}. Há vários motivos para passar argumentos ao fragmento, 611mas um bom motivo é reutilizar a mesma subclasse de {@link 612android.preference.PreferenceFragment} para cada grupo e usar o argumento para especificar 613o arquivo XML de preferências que o fragmento deve carregar.</p> 614 615<p>Por exemplo, a seguir há um fragmento que pode ser reutilizado em vários grupos de configurações, quando 616cada cabeçalho define um argumento {@code <extra>} com a chave {@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">Exibição de cabeçalhos</h3> 637 638<p>Para exibir os cabeçalhos de preferência, é preciso implementar o método de retorno de chamada {@link 639android.preference.PreferenceActivity#onBuildHeaders onBuildHeaders()} e chamar 640{@link android.preference.PreferenceActivity#loadHeadersFromResource 641loadHeadersFromResource()}. Por exemplo:</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>Quando o usuário seleciona um item de uma lista de cabeçalhos, o sistema abre o {@link 653android.preference.PreferenceFragment} associado.</p> 654 655<p class="note"><strong>Observação:</strong> ao usar cabeçalhos de preferência, a subclasse de {@link 656android.preference.PreferenceActivity} não precisa implementar o método {@link 657android.preference.PreferenceActivity#onCreate onCreate()} porque a única tarefa 658necessária para a atividade é carregar os cabeçalhos.</p> 659 660 661<h3 id="BackCompatHeaders">Compatibilidade de versões mais antigas com cabeçalhos de preferência</h3> 662 663<p>Se o aplicativo for compatível com versões de Android anteriores à 3.0, ainda será possível usar cabeçalhos 664para fornecer um layout em dois painéis ao executar no Android 3.0 e versões posteriores. Basta criar um arquivo XML de preferências 665adicional que usa elementos básicos {@link android.preference.Preference 666<Preference>} que se comportam como os itens de cabeçalho (para uso das versões mais antigas 667do Android).</p> 668 669<p>No entanto, em vez de abrir um novo {@link android.preference.PreferenceScreen}, cada elemento {@link 670android.preference.Preference <Preference>} envia um {@link android.content.Intent} 671ao {@link android.preference.PreferenceActivity} que especifica que arquivo XML de preferência 672carregar.</p> 673 674<p>Por exemplo, abaixo há um arquivo XML de cabeçalhos de preferência usado no Android 3.0 675e posterior ({@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>E apresenta-se também um arquivo de preferências que fornece os mesmos cabeçalhos de versões de Android 691mais antigas que a 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>Como a compatibilidade com {@code <preference-headers>} foi adicionada no Android 3.0, o sistema chama 715{@link android.preference.PreferenceActivity#onBuildHeaders onBuildHeaders()} em seu {@link 716android.preference.PreferenceActivity} somente ao executar em Androd 3.0 ou posterior. Para carregar 717o arquivo de cabeçalhos de “legado" ({@code preference_headers_legacy.xml}), é preciso verificar a versãodo Android 718e, se a versão for mais antiga que o Android 3.0 ({@link 719android.os.Build.VERSION_CODES#HONEYCOMB}), chama {@link 720android.preference.PreferenceActivity#addPreferencesFromResource addPreferencesFromResource()} 721para carregar o arquivo de cabeçalho legado. Por exemplo:</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>Depois só resta tratar o {@link android.content.Intent} passado para a atividade 743para identificar que arquivo de preferências carregar. Portanto, para recuperar a ação da intenção e compará-la 744com strings de ações conhecidas usadas nas tags de {@code <intent>} do XML de preferências:</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>Observe que chamadas consecutivas a {@link 768android.preference.PreferenceActivity#addPreferencesFromResource addPreferencesFromResource()} 769empilharão todas as preferências em uma única lista, portanto certifique-se de que seja chamado somente uma vez, encadeando 770as condições com declarações else-if.</p> 771 772 773 774 775 776<h2 id="ReadingPrefs">Leitura de preferências</h2> 777 778<p>Por padrão, todas as preferências do aplicativo são salvas em um arquivo acessível de qualquer lugar 779dentro do aplicativo chamando o método estático {@link 780android.preference.PreferenceManager#getDefaultSharedPreferences 781PreferenceManager.getDefaultSharedPreferences()}. Isso retorna o objeto {@link 782android.content.SharedPreferences} que contém todos os pares de valores-chave associados 783aos objetos {@link android.preference.Preference} usados em {@link 784android.preference.PreferenceActivity}.</p> 785 786<p>Por exemplo, abaixo apresenta-se como ler um dos valores de preferência de outra atividade 787no aplicativo:</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">Escuta de alterações de preferência</h3> 797 798<p>Há alguns motivos pelos quais pode ser necessário ser notificado assim que o usuário altera 799uma das preferências. Para receber um retorno de chamada quando acontece uma alteração em alguma das preferências, 800implemente a interface {@link android.content.SharedPreferences.OnSharedPreferenceChangeListener 801SharedPreference.OnSharedPreferenceChangeListener} e registre a escuta 802para o objeto {@link android.content.SharedPreferences} chamando {@link 803android.content.SharedPreferences#registerOnSharedPreferenceChangeListener 804registerOnSharedPreferenceChangeListener()}.</p> 805 806<p>A interface tem somente um método de retorno de chamada, {@link 807android.content.SharedPreferences.OnSharedPreferenceChangeListener#onSharedPreferenceChanged 808onSharedPreferenceChanged()}, e pode ser mais fácil implementar a interface como parte 809da atividade. Por exemplo:</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>Nesse exemplo, o método verifica se a configuração alterada se destina a uma chave de preferência conhecida. Ele 829chama {@link android.preference.PreferenceActivity#findPreference findPreference()} para obter 830o objeto {@link android.preference.Preference} alterado para que possa modificar o sumário 831do item como uma descrição da seleção do usuário. Ou seja, quando a configuração for uma {@link 832android.preference.ListPreference} ou outra configuração de múltipla escolha, deve-se chamar {@link 833android.preference.Preference#setSummary setSummary()} quando a configuração for alterada para exibir 834o status atual (como a configuração Suspensão mostrada na figura 5).</p> 835 836<p class="note"><strong>Observação:</strong> conforme descrito no documento do Projeto para Android sobre <a href="{@docRoot}design/patterns/settings.html">Configurações</a>, recomendamos atualizar 837o sumário de {@link android.preference.ListPreference} a cada vez que o usuário alterar a preferência 838para descrever a configuração atual.</p> 839 840<p>Para um gerenciamento adequado do ciclo de vida na atividade, recomendamos registrar e remover o registro 841de {@link android.content.SharedPreferences.OnSharedPreferenceChangeListener} durante os retornos de chamada de {@link 842android.app.Activity#onResume} e {@link android.app.Activity#onPause} respectivamente:</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>Atenção:</strong> ao chamar {@link 861android.content.SharedPreferences#registerOnSharedPreferenceChangeListener 862registerOnSharedPreferenceChangeListener()}, o gerenciador de preferências 863não armazena atualmente uma referência à escuta. É preciso armazenar uma referência 864forte à escuta, senão ela será suscetível à coleta de lixo. Recomendamos 865manter uma referência à escuta nos dados de instância de um objeto 866que existirá enquanto a escuta for necessária.</p> 867 868<p>Por exemplo: no código a seguir, o autor da chamada não mantém nenhuma 869referência à escuta. Como resultado, a escuta estará sujeita à coleta de lixo 870e falhará futuramente em algum momento indeterminado:</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>Em vez disso, armazene uma referência à escuta nos dados de instância de um objeto 883que existirá enquanto a escuta for necessária:</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">Gerenciamento de uso de rede</h2> 896 897 898<p>A partir do Android 4.0, o aplicativo Configurações do sistema permite aos usuários ver o quanto 899de dados de rede que os aplicativos usam em primeiro e segundo plano. Portanto, os usuários 900podem desativar os dados em segundo plano de aplicativos individuais. Para evitar que os usuários desativem 901o acesso do aplicativo a dados em segundo plano, deve-se usar a conexão de dados de forma eficiente 902e permitir aos usuários refinar o uso de dados do aplicativo por meio das configurações do aplicativo.<p> 903 904<p>Por exemplo: deve-se permitir ao usuário controlar a frequência de sincronização dos dados do aplicativo para 905uploads/downloads somente quando estiver em Wi-Fi, o aplicativo usar dados em deslocamento etc. Com esses 906controles disponíveis para eles, é bem menos provável que os usuários desativem o acesso do aplicativo a dados 907quando eles se aproximam dos limites que definem nas Configurações do sistema porque, em vez disso, podem controlar 908precisamente a quantidade de dados que o aplicativo usa.</p> 909 910<p>Depois de adicionadas as preferências necessárias em {@link android.preference.PreferenceActivity} 911para controlar os hábitos de dados do aplicativo, deve-se adicionar um filtro de intenções para {@link 912android.content.Intent#ACTION_MANAGE_NETWORK_USAGE} no arquivo de manifesto. Por exemplo:</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>Esse filtro de intenções indica ao sistema que se trata da atividade que controla 924o uso de dados do aplicativo. Assim, quando o usuário inspeciona a quantidade de dados que o aplicativo está usando 925no aplicativo Configurações do sistema, um botão <em>Exibir configurações de aplicativo</em> fica disponível e inicia 926{@link android.preference.PreferenceActivity} para que o usuário refine a quantidade de dados que 927o aplicativo usa.</p> 928 929 930 931 932 933 934 935<h2 id="Custom">Composição de uma preferência personalizada</h2> 936 937<p>A estrutura do Android contém uma variedade de subclasses {@link android.preference.Preference} que permitem 938criar uma IU com diferentes tipos de configurações. 939No entanto, pode ser necessário descobrir uma configuração pra a qual não há nenhuma solução embutida, 940como um seletor de números ou seletor de datas. Nesse caso, será preciso criar uma preferência personalizada, estendendo 941a classe {@link android.preference.Preference} ou uma das outras subclasses.</p> 942 943<p>Ao estender a classe {@link android.preference.Preference}, há algumas coisas importantes 944a fazer:</p> 945 946<ul> 947 <li>Especificar a interface do usuário exibida quando o usuário seleciona as configurações.</li> 948 <li>Salvar os valores da configuração conforme apropriado.</li> 949 <li>Inicializar {@link android.preference.Preference} com o valor atual (ou padrão) 950quando ela é exibida.</li> 951 <li>Fornecer o valor padrão quando solicitado pelo sistema.</li> 952 <li>Se {@link android.preference.Preference} fornece sua própria IU (como uma caixa de diálogo, por exemplo), salve 953e restaure o estado para tratar de alterações de ciclo de vida (como quando o usuário gira a tela).</li> 954</ul> 955 956<p>As seções a seguir descrevem como executar cada uma dessas tarefas.</p> 957 958 959 960<h3 id="CustomSelected">Especificação da interface do usuário</h3> 961 962 <p>Se a classe {@link android.preference.Preference} for estendida, será preciso implementar 963{@link android.preference.Preference#onClick()} para definir a ação que ocorre quando 964o usuário a seleciona. No entanto, a maioria das configurações personalizadas estendem {@link android.preference.DialogPreference} 965para exibir uma caixa de diálogo, o que simplifica o procedimento. Quando se estende {@link 966android.preference.DialogPreference}, é preciso chamar {@link 967android.preference.DialogPreference#setDialogLayoutResource setDialogLayoutResourcs()} na classe 968do construtor para especificar o layout da caixa de diálogo.</p> 969 970 <p>Por exemplo, eis o construtor de um {@link 971android.preference.DialogPreference} personalizado que declara o layout e especifica o texto dos botões padrão 972da caixa de diálogo positiva e negativa:</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">Salvamento do valor da configuração</h3> 992 993<p>Para salvar um valor da configuração a qualquer momento, chame um dos métodos {@code persist*()} da classe {@link 994android.preference.Preference}, como {@link 995android.preference.Preference#persistInt persistInt()} se o valor da configuração for um inteiro 996ou {@link android.preference.Preference#persistBoolean persistBoolean()} para salvar um booleano.</p> 997 998<p class="note"><strong>Observação:</strong> cada {@link android.preference.Preference} pode salvar somente 999um tipo de dados, portanto é preciso usar o método {@code persist*()} adequado para o tipo de dados usado pela 1000{@link android.preference.Preference} personalizada.</p> 1001 1002<p>Quando se opta por persistir, a configuração pode depender da classe {@link 1003android.preference.Preference} estendida. Se {@link 1004android.preference.DialogPreference} for estendida, deve-se persistir o valor somente quando a caixa de diálogo 1005fecha devido a um resultado positivo (o usuário seleciona o botão "OK").</p> 1006 1007<p>Quando uma {@link android.preference.DialogPreference} fecha, o sistema chama o método {@link 1008android.preference.DialogPreference#onDialogClosed onDialogClosed()}. O método contém um argumento 1009booleano que especifica se o resultado do usuário é "positivo" — se o valor é 1010<code>true</code> e, em seguida, o usuário selecionou o botão positivo e você deve salvar o novo valor. Por 1011exemplo:</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>Nesse exemplo, <code>mNewValue</code> é um membro da classe que retém o valor atual 1024da configuração. A chamada de {@link android.preference.Preference#persistInt persistInt()} salva o valor 1025no arquivo {@link android.content.SharedPreferences} (usando automaticamente a chave 1026especificada no arquivo XML dessa {@link android.preference.Preference}).</p> 1027 1028 1029<h3 id="CustomInitialize">Inicialização do valor atual</h3> 1030 1031<p>Quando o sistema adiciona o {@link android.preference.Preference} à tela, ele chama 1032{@link android.preference.Preference#onSetInitialValue onSetInitialValue()} para notificar 1033se a configuração tem um valor persistido. Se não houver valor persistido, essa chamada fornece 1034o valor padrão.</p> 1035 1036<p>O método {@link android.preference.Preference#onSetInitialValue onSetInitialValue()} passa 1037um booleano, <code>restorePersistedValue</code>, para indicar se um valor já foi persistido 1038para a configuração. Se for <code>true</code>, deve-se recuperar o valor persistindo chamando-se 1039 um dos métodos {@code getPersisted*()} da classe {@link 1040android.preference.Preference}, como {@link 1041android.preference.Preference#getPersistedInt getPersistedInt()} para um valor inteiro. Geralmente 1042se recupera o valor persistido para atualizar adequadamente a IU de forma a refletir 1043o valor salvo anteriormente.</p> 1044 1045<p>Se <code>restorePersistedValue</code> for <code>false</code>, deve-se 1046usar o valor padrão passado no segundo argumento.</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>Cada método {@code getPersisted*()} pega um argumento que especifica o valor 1063padrão a usar caso não haja nenhum valor persistido ou se a chave não existir. No 1064exemplo acima, uma constante local é usada para especificar o valor padrão se {@link 1065android.preference.Preference#getPersistedInt getPersistedInt()} não puder retornar um valor persistido.</p> 1066 1067<p class="caution"><strong>Atenção:</strong> <strong>não</strong> é possível usar 1068<code>defaultValue</code> como valor padrão no método {@code getPersisted*()} porque 1069seu valor é sempre nulo quando <code>restorePersistedValue</code> é <code>true</code>.</p> 1070 1071 1072<h3 id="CustomDefault">Fornecimento de um valor padrão</h3> 1073 1074<p>Se a instância da classe {@link android.preference.Preference} especificar um valor padrão 1075(com o atributo {@code android:defaultValue}), 1076o sistema chama {@link android.preference.Preference#onGetDefaultValue 1077onGetDefaultValue()} quando instancia o objeto para recuperar o valor. É preciso 1078implementar esse método para que o sistema salve o valor padrão em {@link 1079android.content.SharedPreferences}. Por exemplo:</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>Os argumentos do método oferecem todo o necessário: a matriz de atributos e a posição 1089do índice do {@code android:defaultValue}, que é preciso recuperar. É preciso implementar esse método 1090para extrair o valor padrão do atributo porque deve-se especificar um valor padrão 1091local para o atributo caso o valor seja indefinido.</p> 1092 1093 1094 1095<h3 id="CustomSaveState">Salvamento e restauração do estado da preferência</h3> 1096 1097<p>Como um {@link android.view.View} em um layout, a subclasse {@link android.preference.Preference} 1098é responsável por salvar e restaurar seu estado caso a atividade ou fragmento seja 1099reiniciado (como ocorre quando o usuário gira a tela). Para salvar e restaurar 1100adequadamente o estado da classe {@link android.preference.Preference}, é preciso implementar 1101os métodos de retorno de chamada do ciclo de vida {@link android.preference.Preference#onSaveInstanceState 1102onSaveInstanceState()} e {@link 1103android.preference.Preference#onRestoreInstanceState onRestoreInstanceState()}.</p> 1104 1105<p>O estado de {@link android.preference.Preference} é definido por um objeto que implementa 1106a interface {@link android.os.Parcelable}. A estrutura do Android fornece esse objeto 1107como um ponto inicial para definir o objeto de estado: a classe {@link 1108android.preference.Preference.BaseSavedState}.</p> 1109 1110<p>Para definir como a classe {@link android.preference.Preference} salva seu estado, deve-se estender 1111a classe {@link android.preference.Preference.BaseSavedState}. É preciso substituir 1112alguns métodos e definir o objeto {@link android.preference.Preference.BaseSavedState#CREATOR}. 1113</p> 1114 1115<p>Na maioria dos aplicativos, é possível copiar a implementação a seguir e simplesmente alterar as linhas 1116que tratam o {@code value} se a subclasse {@link android.preference.Preference} salvar um tipo 1117de dados que não seja um inteiro.</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>Com a implementação acima de {@link android.preference.Preference.BaseSavedState} adicionada 1158ao aplicativo (geralmente como uma subclasse da subclasse {@link android.preference.Preference}), 1159é preciso implementar os métodos {@link android.preference.Preference#onSaveInstanceState 1160onSaveInstanceState()} e {@link 1161android.preference.Preference#onRestoreInstanceState onRestoreInstanceState()} 1162da subclasse {@link android.preference.Preference}.</p> 1163 1164<p>Por exemplo:</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