| page.title=Settings |
| page.tags=preference,preferenceactivity,preferencefragment |
| |
| @jd:body |
| |
| |
| <div id="qv-wrapper"> |
| <div id="qv"> |
| |
| <h2>In this document</h2> |
| <ol> |
| <li><a href="#Overview">Overview</a> |
| <ol> |
| <li><a href="#SettingTypes">Preferences</a></li> |
| </ol> |
| </li> |
| <li><a href="#DefiningPrefs">Defining Preferences in XML</a> |
| <ol> |
| <li><a href="#Groups">Creating setting groups</a></li> |
| <li><a href="#Intents">Using intents</a></li> |
| </ol> |
| </li> |
| <li><a href="#Activity">Creating a Preference Activity</a></li> |
| <li><a href="#Fragment">Using Preference Fragments</a></li> |
| <li><a href="#Defaults">Setting Default Values</a></li> |
| <li><a href="#PreferenceHeaders">Using Preference Headers</a> |
| <ol> |
| <li><a href="#CreateHeaders">Creating the headers file</a></li> |
| <li><a href="#DisplayHeaders">Displaying the headers</a></li> |
| <li><a href="#BackCompatHeaders">Supporting older versions with preference headers</a></li> |
| </ol> |
| </li> |
| <li><a href="#ReadingPrefs">Reading Preferences</a> |
| <ol> |
| <li><a href="#Listening">Listening for preference changes</a></li> |
| </ol> |
| </li> |
| <li><a href="#NetworkUsage">Managing Network Usage</a></li> |
| <li><a href="#Custom">Building a Custom Preference</a> |
| <ol> |
| <li><a href="#CustomSelected">Specifying the user interface</a></li> |
| <li><a href="#CustomSave">Saving the setting's value</a></li> |
| <li><a href="#CustomInitialize">Initializing the current value</a></li> |
| <li><a href="#CustomDefault">Providing a default value</a></li> |
| <li><a href="#CustomSaveState">Saving and restoring the Preference's state</a></li> |
| </ol> |
| </li> |
| </ol> |
| |
| <h2>Key classes</h2> |
| <ol> |
| <li>{@link android.preference.Preference}</li> |
| <li>{@link android.preference.PreferenceActivity}</li> |
| <li>{@link android.preference.PreferenceFragment}</li> |
| </ol> |
| |
| |
| <h2>See also</h2> |
| <ol> |
| <li><a |
| href="{@docRoot}design/patterns/settings.html">Settings design guide</a></li> |
| </ol> |
| </div> |
| </div> |
| |
| |
| |
| |
| <p>Applications often include settings that allow users to modify app features and behaviors. For |
| example, some apps allow users to specify whether notifications are enabled or specify how often the |
| application syncs data with the cloud.</p> |
| |
| <p>If you want to provide settings for your app, you should use |
| Android's {@link android.preference.Preference} APIs to build an interface that's consistent with |
| the user experience in other Android apps (including the system settings). This document describes |
| how to build your app settings using {@link android.preference.Preference} APIs.</p> |
| |
| <div class="note design"> |
| <p><strong>Settings Design</strong></p> |
| <p>For information about how to design your settings, read the <a |
| href="{@docRoot}design/patterns/settings.html">Settings</a> design guide.</p> |
| </div> |
| |
| |
| <img src="{@docRoot}images/ui/settings/settings.png" alt="" width="435" /> |
| <p class="img-caption"><strong>Figure 1.</strong> Screenshots from the Android Messaging app's |
| settings. Selecting an item defined by a {@link android.preference.Preference} |
| opens an interface to change the setting.</p> |
| |
| |
| |
| |
| <h2 id="Overview">Overview</h2> |
| |
| <p>Instead of using {@link android.view.View} objects to build the user interface, settings are |
| built using various subclasses of the {@link android.preference.Preference} class that you |
| declare in an XML file.</p> |
| |
| <p>A {@link android.preference.Preference} object is the building block for a single |
| setting. Each {@link android.preference.Preference} appears as an item in a list and provides the |
| appropriate UI for users to modify the setting. For example, a {@link |
| android.preference.CheckBoxPreference} creates a list item that shows a checkbox, and a {@link |
| android.preference.ListPreference} creates an item that opens a dialog with a list of choices.</p> |
| |
| <p>Each {@link android.preference.Preference} you add has a corresponding key-value pair that |
| the system uses to save the setting in a default {@link android.content.SharedPreferences} |
| file for your app's settings. When the user changes a setting, the system updates the corresponding |
| value in the {@link android.content.SharedPreferences} file for you. The only time you should |
| directly interact with the associated {@link android.content.SharedPreferences} file is when you |
| need to read the value in order to determine your app's behavior based on the user's setting.</p> |
| |
| <p>The value saved in {@link android.content.SharedPreferences} for each setting can be one of the |
| following data types:</p> |
| |
| <ul> |
| <li>Boolean</li> |
| <li>Float</li> |
| <li>Int</li> |
| <li>Long</li> |
| <li>String</li> |
| <li>String {@link java.util.Set}</li> |
| </ul> |
| |
| <p>Because your app's settings UI is built using {@link android.preference.Preference} objects |
| instead of |
| {@link android.view.View} objects, you need to use a specialized {@link android.app.Activity} or |
| {@link android.app.Fragment} subclass to display the list settings:</p> |
| |
| <ul> |
| <li>If your app supports versions of Android older than 3.0 (API level 10 and lower), you must |
| build the activity as an extension of the {@link android.preference.PreferenceActivity} class.</li> |
| <li>On Android 3.0 and later, you should instead use a traditional {@link android.app.Activity} |
| that hosts a {@link android.preference.PreferenceFragment} that displays your app settings. |
| However, you can also use {@link android.preference.PreferenceActivity} to create a two-pane layout |
| for large screens when you have multiple groups of settings.</li> |
| </ul> |
| |
| <p>How to set up your {@link android.preference.PreferenceActivity} and instances of {@link |
| android.preference.PreferenceFragment} is discussed in the sections about <a |
| href="#Activity">Creating a Preference Activity</a> and <a href="#Fragment">Using |
| Preference Fragments</a>.</p> |
| |
| |
| <h3 id="SettingTypes">Preferences</h3> |
| |
| <p>Every setting for your app is represented by a specific subclass of the {@link |
| android.preference.Preference} class. Each subclass includes a set of core properties that allow you |
| to specify things such as a title for the setting and the default value. Each subclass also provides |
| its own specialized properties and user interface. For instance, figure 1 shows a screenshot from |
| the Messaging app's settings. Each list item in the settings screen is backed by a different {@link |
| android.preference.Preference} object.</p> |
| |
| <p>A few of the most common preferences are:</p> |
| |
| <dl> |
| <dt>{@link android.preference.CheckBoxPreference}</dt> |
| <dd>Shows an item with a checkbox for a setting that is either enabled or disabled. The saved |
| value is a boolean (<code>true</code> if it's checked).</dd> |
| |
| <dt>{@link android.preference.ListPreference}</dt> |
| <dd>Opens a dialog with a list of radio buttons. The saved value |
| can be any one of the supported value types (listed above).</dd> |
| |
| <dt>{@link android.preference.EditTextPreference}</dt> |
| <dd>Opens a dialog with an {@link android.widget.EditText} widget. The saved value is a {@link |
| java.lang.String}.</dd> |
| </dl> |
| |
| <p>See the {@link android.preference.Preference} class for a list of all other subclasses and their |
| corresponding properties.</p> |
| |
| <p>Of course, the built-in classes don't accommodate every need and your application might require |
| something more specialized. For example, the platform currently does not provide a {@link |
| android.preference.Preference} class for picking a number or a date. So you might need to define |
| your own {@link android.preference.Preference} subclass. For help doing so, see the section about <a |
| href="#Custom">Building a Custom Preference</a>.</p> |
| |
| |
| |
| <h2 id="DefiningPrefs">Defining Preferences in XML</h2> |
| |
| <p>Although you can instantiate new {@link android.preference.Preference} objects at runtime, you |
| should define your list of settings in XML with a hierarchy of {@link android.preference.Preference} |
| objects. Using an XML file to define your collection of settings is preferred because the file |
| provides an easy-to-read structure that's simple to update. Also, your app's settings are |
| generally pre-determined, although you can still modify the collection at runtime.</p> |
| |
| <p>Each {@link android.preference.Preference} subclass can be declared with an XML element that |
| matches the class name, such as {@code <CheckBoxPreference>}.</p> |
| |
| <p>You must save the XML file in the {@code res/xml/} directory. Although you can name the file |
| anything you want, it's traditionally named {@code preferences.xml}. You usually need only one file, |
| because branches in the hierarchy (that open their own list of settings) are declared using nested |
| instances of {@link android.preference.PreferenceScreen}.</p> |
| |
| <p class="note"><strong>Note:</strong> If you want to create a multi-pane layout for your |
| settings, then you need separate XML files for each fragment.</p> |
| |
| <p>The root node for the XML file must be a {@link android.preference.PreferenceScreen |
| <PreferenceScreen>} element. Within this element is where you add each {@link |
| android.preference.Preference}. Each child you add within the |
| {@link android.preference.PreferenceScreen <PreferenceScreen>} element appears as a single |
| item in the list of settings.</p> |
| |
| <p>For example:</p> |
| |
| <pre> |
| <?xml version="1.0" encoding="utf-8"?> |
| <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> |
| <CheckBoxPreference |
| android:key="pref_sync" |
| android:title="@string/pref_sync" |
| android:summary="@string/pref_sync_summ" |
| android:defaultValue="true" /> |
| <ListPreference |
| android:dependency="pref_sync" |
| android:key="pref_syncConnectionType" |
| android:title="@string/pref_syncConnectionType" |
| android:dialogTitle="@string/pref_syncConnectionType" |
| android:entries="@array/pref_syncConnectionTypes_entries" |
| android:entryValues="@array/pref_syncConnectionTypes_values" |
| android:defaultValue="@string/pref_syncConnectionTypes_default" /> |
| </PreferenceScreen> |
| </pre> |
| |
| <p>In this example, there's a {@link android.preference.CheckBoxPreference} and a {@link |
| android.preference.ListPreference}. Both items include the following three attributes:</p> |
| |
| <dl> |
| <dt>{@code android:key}</dt> |
| <dd>This attribute is required for preferences that persist a data value. It specifies the unique |
| key (a string) the system uses when saving this setting's value in the {@link |
| android.content.SharedPreferences}. |
| <p>The only instances in which this attribute is <em>not required</em> is when the preference is a |
| {@link android.preference.PreferenceCategory} or {@link android.preference.PreferenceScreen}, or the |
| preference specifies an {@link android.content.Intent} to invoke (with an <a |
| href="#Intents">{@code <intent>}</a> element) or a {@link android.app.Fragment} to display (with an <a |
| href="{@docRoot}reference/android/preference/Preference.html#attr_android:fragment">{@code |
| android:fragment}</a> attribute).</p> |
| </dd> |
| <dt>{@code android:title}</dt> |
| <dd>This provides a user-visible name for the setting.</dd> |
| <dt>{@code android:defaultValue}</dt> |
| <dd>This specifies the initial value that the system should set in the {@link |
| android.content.SharedPreferences} file. You should supply a default value for all |
| settings.</dd> |
| </dl> |
| |
| <p>For information about all other supported attributes, see the {@link |
| android.preference.Preference} (and respective subclass) documentation.</p> |
| |
| |
| <div class="figure" style="width:300px"> |
| <img src="{@docRoot}images/ui/settings/settings-titles.png" alt="" /> |
| <p class="img-caption"><strong>Figure 2.</strong> Setting categories |
| with titles. <br/><b>1.</b> The category is specified by the {@link |
| android.preference.PreferenceCategory <PreferenceCategory>} element. <br/><b>2.</b> The title is |
| specified with the {@code android:title} attribute.</p> |
| </div> |
| |
| |
| <p>When your list of settings exceeds about 10 items, you might want to add titles to |
| define groups of settings or display those groups in a |
| separate screen. These options are described in the following sections.</p> |
| |
| |
| <h3 id="Groups">Creating setting groups</h3> |
| |
| <p>If you present a list of 10 or more settings, users |
| may have difficulty scanning, comprehending, and processing them. You can remedy this by |
| dividing some or all of the settings into groups, effectively turning one long list into multiple |
| shorter lists. A group of related settings can be presented in one of two ways:</p> |
| |
| <ul> |
| <li><a href="#Titles">Using titles</a></li> |
| <li><a href="#Subscreens">Using subscreens</a></li> |
| </ul> |
| |
| <p>You can use one or both of these grouping techniques to organize your app's settings. When |
| deciding which to use and how to divide your settings, you should follow the guidelines in Android |
| Design's <a href="{@docRoot}design/patterns/settings.html">Settings</a> guide.</p> |
| |
| |
| <h4 id="Titles">Using titles</h4> |
| |
| <p>If you want to provide dividers with headings between groups of settings (as shown in figure 2), |
| place each group of {@link android.preference.Preference} objects inside a {@link |
| android.preference.PreferenceCategory}.</p> |
| |
| <p>For example:</p> |
| |
| <pre> |
| <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> |
| <PreferenceCategory |
| android:title="@string/pref_sms_storage_title" |
| android:key="pref_key_storage_settings"> |
| <CheckBoxPreference |
| android:key="pref_key_auto_delete" |
| android:summary="@string/pref_summary_auto_delete" |
| android:title="@string/pref_title_auto_delete" |
| android:defaultValue="false"... /> |
| <Preference |
| android:key="pref_key_sms_delete_limit" |
| android:dependency="pref_key_auto_delete" |
| android:summary="@string/pref_summary_delete_limit" |
| android:title="@string/pref_title_sms_delete"... /> |
| <Preference |
| android:key="pref_key_mms_delete_limit" |
| android:dependency="pref_key_auto_delete" |
| android:summary="@string/pref_summary_delete_limit" |
| android:title="@string/pref_title_mms_delete" ... /> |
| </PreferenceCategory> |
| ... |
| </PreferenceScreen> |
| </pre> |
| |
| |
| <h4 id="Subscreens">Using subscreens</h4> |
| |
| <p>If you want to place groups of settings into a subscreen (as shown in figure 3), place the group |
| of {@link android.preference.Preference} objects inside a {@link |
| android.preference.PreferenceScreen}.</p> |
| |
| <img src="{@docRoot}images/ui/settings/settings-subscreen.png" alt="" /> |
| <p class="img-caption"><strong>Figure 3.</strong> Setting subscreens. The {@code |
| <PreferenceScreen>} element |
| creates an item that, when selected, opens a separate list to display the nested settings.</p> |
| |
| <p>For example:</p> |
| |
| <pre> |
| <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> |
| <!-- opens a subscreen of settings --> |
| <PreferenceScreen |
| android:key="button_voicemail_category_key" |
| android:title="@string/voicemail" |
| android:persistent="false"> |
| <ListPreference |
| android:key="button_voicemail_provider_key" |
| android:title="@string/voicemail_provider" ... /> |
| <!-- opens another nested subscreen --> |
| <PreferenceScreen |
| android:key="button_voicemail_setting_key" |
| android:title="@string/voicemail_settings" |
| android:persistent="false"> |
| ... |
| </PreferenceScreen> |
| <RingtonePreference |
| android:key="button_voicemail_ringtone_key" |
| android:title="@string/voicemail_ringtone_title" |
| android:ringtoneType="notification" ... /> |
| ... |
| </PreferenceScreen> |
| ... |
| </PreferenceScreen> |
| </pre> |
| |
| |
| <h3 id="Intents">Using intents</h3> |
| |
| <p>In some cases, you might want a preference item to open a different activity instead of a |
| settings screen, such as a web browser to view a web page. To invoke an {@link |
| android.content.Intent} when the user selects a preference item, add an {@code <intent>} |
| element as a child of the corresponding {@code <Preference>} element.</p> |
| |
| <p>For example, here's how you can use a preference item to open a web page:</p> |
| |
| <pre> |
| <Preference android:title="@string/prefs_web_page" > |
| <intent android:action="android.intent.action.VIEW" |
| android:data="http://www.example.com" /> |
| </Preference> |
| </pre> |
| |
| <p>You can create both implicit and explicit intents using the following attributes:</p> |
| |
| <dl> |
| <dt>{@code android:action}</dt> |
| <dd>The action to assign, as per the {@link android.content.Intent#setAction setAction()} |
| method.</dd> |
| <dt>{@code android:data}</dt> |
| <dd>The data to assign, as per the {@link android.content.Intent#setData setData()} method.</dd> |
| <dt>{@code android:mimeType}</dt> |
| <dd>The MIME type to assign, as per the {@link android.content.Intent#setType setType()} |
| method.</dd> |
| <dt>{@code android:targetClass}</dt> |
| <dd>The class part of the component name, as per the {@link android.content.Intent#setComponent |
| setComponent()} method.</dd> |
| <dt>{@code android:targetPackage}</dt> |
| <dd>The package part of the component name, as per the {@link |
| android.content.Intent#setComponent setComponent()} method.</dd> |
| </dl> |
| |
| |
| |
| <h2 id="Activity">Creating a Preference Activity</h2> |
| |
| <p>To display your settings in an activity, extend the {@link |
| android.preference.PreferenceActivity} class. This is an extension of the traditional {@link |
| android.app.Activity} class that displays a list of settings based on a hierarchy of {@link |
| android.preference.Preference} objects. The {@link android.preference.PreferenceActivity} |
| automatically persists the settings associated with each {@link |
| android.preference.Preference} when the user makes a change.</p> |
| |
| <p class="note"><strong>Note:</strong> If you're developing your application for Android 3.0 and |
| higher, you should instead use {@link android.preference.PreferenceFragment}. Go to the next |
| section about <a href="#Fragment">Using Preference Fragments</a>.</p> |
| |
| <p>The most important thing to remember is that you do not load a layout of views during the {@link |
| android.preference.PreferenceActivity#onCreate onCreate()} callback. Instead, you call {@link |
| android.preference.PreferenceActivity#addPreferencesFromResource addPreferencesFromResource()} to |
| add the preferences you've declared in an XML file to the activity. For example, here's the bare |
| minimum code required for a functional {@link android.preference.PreferenceActivity}:</p> |
| |
| <pre> |
| public class SettingsActivity extends PreferenceActivity { |
| @Override |
| public void onCreate(Bundle savedInstanceState) { |
| super.onCreate(savedInstanceState); |
| addPreferencesFromResource(R.xml.preferences); |
| } |
| } |
| </pre> |
| |
| <p>This is actually enough code for some apps, because as soon as the user modifies a preference, |
| the system saves the changes to a default {@link android.content.SharedPreferences} file that your |
| other application components can read when you need to check the user's settings. Many apps, |
| however, require a little more code in order to listen for changes that occur to the preferences. |
| For information about listening to changes in the {@link android.content.SharedPreferences} file, |
| see the section about <a href="#ReadingPrefs">Reading Preferences</a>.</p> |
| |
| |
| |
| |
| <h2 id="Fragment">Using Preference Fragments</h2> |
| |
| <p>If you're developing for Android 3.0 (API level 11) and higher, you should use a {@link |
| android.preference.PreferenceFragment} to display your list of {@link android.preference.Preference} |
| objects. You can add a {@link android.preference.PreferenceFragment} to any activity—you don't |
| need to use {@link android.preference.PreferenceActivity}.</p> |
| |
| <p><a href="{@docRoot}guide/components/fragments.html">Fragments</a> provide a more |
| flexible architecture for your application, compared to using activities alone, no matter what kind |
| of activity you're building. As such, we suggest you use {@link |
| android.preference.PreferenceFragment} to control the display of your settings instead of {@link |
| android.preference.PreferenceActivity} when possible.</p> |
| |
| <p>Your implementation of {@link android.preference.PreferenceFragment} can be as simple as |
| defining the {@link android.preference.PreferenceFragment#onCreate onCreate()} method to load a |
| preferences file with {@link android.preference.PreferenceFragment#addPreferencesFromResource |
| addPreferencesFromResource()}. For example:</p> |
| |
| <pre> |
| public static class SettingsFragment extends PreferenceFragment { |
| @Override |
| public void onCreate(Bundle savedInstanceState) { |
| super.onCreate(savedInstanceState); |
| |
| // Load the preferences from an XML resource |
| addPreferencesFromResource(R.xml.preferences); |
| } |
| ... |
| } |
| </pre> |
| |
| <p>You can then add this fragment to an {@link android.app.Activity} just as you would for any other |
| {@link android.app.Fragment}. For example:</p> |
| |
| <pre> |
| public class SettingsActivity extends Activity { |
| @Override |
| protected void onCreate(Bundle savedInstanceState) { |
| super.onCreate(savedInstanceState); |
| |
| // Display the fragment as the main content. |
| getFragmentManager().beginTransaction() |
| .replace(android.R.id.content, new SettingsFragment()) |
| .commit(); |
| } |
| } |
| </pre> |
| |
| <p class="note"><strong>Note:</strong> A {@link android.preference.PreferenceFragment} doesn't have |
| a its own {@link android.content.Context} object. If you need a {@link android.content.Context} |
| object, you can call {@link android.app.Fragment#getActivity()}. However, be careful to call |
| {@link android.app.Fragment#getActivity()} only when the fragment is attached to an activity. When |
| the fragment is not yet attached, or was detached during the end of its lifecycle, {@link |
| android.app.Fragment#getActivity()} will return null.</p> |
| |
| |
| <h2 id="Defaults">Setting Default Values</h2> |
| |
| <p>The preferences you create probably define some important behaviors for your application, so it's |
| necessary that you initialize the associated {@link android.content.SharedPreferences} file with |
| default values for each {@link android.preference.Preference} when the user first opens your |
| application.</p> |
| |
| <p>The first thing you must do is specify a default value for each {@link |
| android.preference.Preference} |
| object in your XML file using the {@code android:defaultValue} attribute. The value can be any data |
| type that is appropriate for the corresponding {@link android.preference.Preference} object. For |
| example:</p> |
| |
| <pre> |
| <!-- default value is a boolean --> |
| <CheckBoxPreference |
| android:defaultValue="true" |
| ... /> |
| |
| <!-- default value is a string --> |
| <ListPreference |
| android:defaultValue="@string/pref_syncConnectionTypes_default" |
| ... /> |
| </pre> |
| |
| <p>Then, from the {@link android.app.Activity#onCreate onCreate()} method in your application's main |
| activity—and in any other activity through which the user may enter your application for the |
| first time—call {@link android.preference.PreferenceManager#setDefaultValues |
| setDefaultValues()}:</p> |
| |
| <pre> |
| PreferenceManager.setDefaultValues(this, R.xml.advanced_preferences, false); |
| </pre> |
| |
| <p>Calling this during {@link android.app.Activity#onCreate onCreate()} ensures that your |
| application is properly initialized with default settings, which your application might need to |
| read in order to determine some behaviors (such as whether to download data while on a |
| cellular network).</p> |
| |
| <p>This method takes three arguments:</p> |
| <ul> |
| <li>Your application {@link android.content.Context}.</li> |
| <li>The resource ID for the preference XML file for which you want to set the default values.</li> |
| <li>A boolean indicating whether the default values should be set more than once. |
| <p>When <code>false</code>, the system sets the default values only if this method has never been |
| called in the past (or the {@link android.preference.PreferenceManager#KEY_HAS_SET_DEFAULT_VALUES} |
| in the default value shared preferences file is false).</p></li> |
| </ul> |
| |
| <p>As long as you set the third argument to <code>false</code>, you can safely call this method |
| every time your activity starts without overriding the user's saved preferences by resetting them to |
| the defaults. However, if you set it to <code>true</code>, you will override any previous |
| values with the defaults.</p> |
| |
| |
| |
| <h2 id="PreferenceHeaders">Using Preference Headers</h2> |
| |
| <p>In rare cases, you might want to design your settings such that the first screen |
| displays only a list of <a href="#Subscreens">subscreens</a> (such as in the system Settings app, |
| as shown in figures 4 and 5). When you're developing such a design for Android 3.0 and higher, you |
| should use a new "headers" feature in Android 3.0, instead of building subscreens with nested |
| {@link android.preference.PreferenceScreen} elements.</p> |
| |
| <p>To build your settings with headers, you need to:</p> |
| <ol> |
| <li>Separate each group of settings into separate instances of {@link |
| android.preference.PreferenceFragment}. That is, each group of settings needs a separate XML |
| file.</li> |
| <li>Create an XML headers file that lists each settings group and declares which fragment |
| contains the corresponding list of settings.</li> |
| <li>Extend the {@link android.preference.PreferenceActivity} class to host your settings.</li> |
| <li>Implement the {@link |
| android.preference.PreferenceActivity#onBuildHeaders onBuildHeaders()} callback to specify the |
| headers file.</li> |
| </ol> |
| |
| <p>A great benefit to using this design is that {@link android.preference.PreferenceActivity} |
| automatically presents the two-pane layout shown in figure 4 when running on large screens.</p> |
| |
| <p>Even if your application supports versions of Android older than 3.0, you can build your |
| application to use {@link android.preference.PreferenceFragment} for a two-pane presentation on |
| newer devices while still supporting a traditional multi-screen hierarchy on older |
| devices (see the section about <a href="#BackCompatHeaders">Supporting older versions with |
| preference headers</a>).</p> |
| |
| <img src="{@docRoot}images/ui/settings/settings-headers-tablet.png" alt="" /> |
| <p class="img-caption"><strong>Figure 4.</strong> Two-pane layout with headers. <br/><b>1.</b> The |
| headers are defined with an XML headers file. <br/><b>2.</b> Each group of settings is defined by a |
| {@link android.preference.PreferenceFragment} that's specified by a {@code <header>} element in |
| the headers file.</p> |
| |
| <img src="{@docRoot}images/ui/settings/settings-headers-handset.png" alt="" /> |
| <p class="img-caption"><strong>Figure 5.</strong> A handset device with setting headers. When an |
| item is selected, the associated {@link android.preference.PreferenceFragment} replaces the |
| headers.</p> |
| |
| |
| <h3 id="CreateHeaders" style="clear:left">Creating the headers file</h3> |
| |
| <p>Each group of settings in your list of headers is specified by a single {@code <header>} |
| element inside a root {@code <preference-headers>} element. For example:</p> |
| |
| <pre> |
| <?xml version="1.0" encoding="utf-8"?> |
| <preference-headers xmlns:android="http://schemas.android.com/apk/res/android"> |
| <header |
| android:fragment="com.example.prefs.SettingsActivity$SettingsFragmentOne" |
| android:title="@string/prefs_category_one" |
| android:summary="@string/prefs_summ_category_one" /> |
| <header |
| android:fragment="com.example.prefs.SettingsActivity$SettingsFragmentTwo" |
| android:title="@string/prefs_category_two" |
| android:summary="@string/prefs_summ_category_two" > |
| <!-- key/value pairs can be included as arguments for the fragment. --> |
| <extra android:name="someKey" android:value="someHeaderValue" /> |
| </header> |
| </preference-headers> |
| </pre> |
| |
| <p>With the {@code android:fragment} attribute, each header declares an instance of {@link |
| android.preference.PreferenceFragment} that should open when the user selects the header.</p> |
| |
| <p>The {@code <extras>} element allows you to pass key-value pairs to the fragment in a {@link |
| android.os.Bundle}. The fragment can retrieve the arguments by calling {@link |
| android.app.Fragment#getArguments()}. You might pass arguments to the fragment for a variety of |
| reasons, but one good reason is to reuse the same subclass of {@link |
| android.preference.PreferenceFragment} for each group and use the argument to specify which |
| preferences XML file the fragment should load.</p> |
| |
| <p>For example, here's a fragment that can be reused for multiple settings groups, when each |
| header defines an {@code <extra>} argument with the {@code "settings"} key:</p> |
| |
| <pre> |
| public static class SettingsFragment extends PreferenceFragment { |
| @Override |
| public void onCreate(Bundle savedInstanceState) { |
| super.onCreate(savedInstanceState); |
| |
| String settings = getArguments().getString("settings"); |
| if ("notifications".equals(settings)) { |
| addPreferencesFromResource(R.xml.settings_wifi); |
| } else if ("sync".equals(settings)) { |
| addPreferencesFromResource(R.xml.settings_sync); |
| } |
| } |
| } |
| </pre> |
| |
| |
| |
| <h3 id="DisplayHeaders">Displaying the headers</h3> |
| |
| <p>To display the preference headers, you must implement the {@link |
| android.preference.PreferenceActivity#onBuildHeaders onBuildHeaders()} callback method and call |
| {@link android.preference.PreferenceActivity#loadHeadersFromResource |
| loadHeadersFromResource()}. For example:</p> |
| |
| <pre> |
| public class SettingsActivity extends PreferenceActivity { |
| @Override |
| public void onBuildHeaders(List<Header> target) { |
| loadHeadersFromResource(R.xml.preference_headers, target); |
| } |
| } |
| </pre> |
| |
| <p>When the user selects an item from the list of headers, the system opens the associated {@link |
| android.preference.PreferenceFragment}.</p> |
| |
| <p class="note"><strong>Note:</strong> When using preference headers, your subclass of {@link |
| android.preference.PreferenceActivity} doesn't need to implement the {@link |
| android.preference.PreferenceActivity#onCreate onCreate()} method, because the only required |
| task for the activity is to load the headers.</p> |
| |
| |
| <h3 id="BackCompatHeaders">Supporting older versions with preference headers</h3> |
| |
| <p>If your application supports versions of Android older than 3.0, you can still use headers to |
| provide a two-pane layout when running on Android 3.0 and higher. All you need to do is create an |
| additional preferences XML file that uses basic {@link android.preference.Preference |
| <Preference>} elements that behave like the header items (to be used by the older Android |
| versions).</p> |
| |
| <p>Instead of opening a new {@link android.preference.PreferenceScreen}, however, each of the {@link |
| android.preference.Preference <Preference>} elements sends an {@link android.content.Intent} to |
| the {@link android.preference.PreferenceActivity} that specifies which preference XML file to |
| load.</p> |
| |
| <p>For example, here's an XML file for preference headers that is used on Android 3.0 |
| and higher ({@code res/xml/preference_headers.xml}):</p> |
| |
| <pre> |
| <preference-headers xmlns:android="http://schemas.android.com/apk/res/android"> |
| <header |
| android:fragment="com.example.prefs.SettingsFragmentOne" |
| android:title="@string/prefs_category_one" |
| android:summary="@string/prefs_summ_category_one" /> |
| <header |
| android:fragment="com.example.prefs.SettingsFragmentTwo" |
| android:title="@string/prefs_category_two" |
| android:summary="@string/prefs_summ_category_two" /> |
| </preference-headers> |
| </pre> |
| |
| <p>And here is a preference file that provides the same headers for versions older than |
| Android 3.0 ({@code res/xml/preference_headers_legacy.xml}):</p> |
| |
| <pre> |
| <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> |
| <Preference |
| android:title="@string/prefs_category_one" |
| android:summary="@string/prefs_summ_category_one" > |
| <intent |
| android:targetPackage="com.example.prefs" |
| android:targetClass="com.example.prefs.SettingsActivity" |
| android:action="com.example.prefs.PREFS_ONE" /> |
| </Preference> |
| <Preference |
| android:title="@string/prefs_category_two" |
| android:summary="@string/prefs_summ_category_two" > |
| <intent |
| android:targetPackage="com.example.prefs" |
| android:targetClass="com.example.prefs.SettingsActivity" |
| android:action="com.example.prefs.PREFS_TWO" /> |
| </Preference> |
| </PreferenceScreen> |
| </pre> |
| |
| <p>Because support for {@code <preference-headers>} was added in Android 3.0, the system calls |
| {@link android.preference.PreferenceActivity#onBuildHeaders onBuildHeaders()} in your {@link |
| android.preference.PreferenceActivity} only when running on Androd 3.0 or higher. In order to load |
| the "legacy" headers file ({@code preference_headers_legacy.xml}), you must check the Android |
| version and, if the version is older than Android 3.0 ({@link |
| android.os.Build.VERSION_CODES#HONEYCOMB}), call {@link |
| android.preference.PreferenceActivity#addPreferencesFromResource addPreferencesFromResource()} to |
| load the legacy header file. For example:</p> |
| |
| <pre> |
| @Override |
| public void onCreate(Bundle savedInstanceState) { |
| super.onCreate(savedInstanceState); |
| ... |
| |
| if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { |
| // Load the legacy preferences headers |
| addPreferencesFromResource(R.xml.preference_headers_legacy); |
| } |
| } |
| |
| // Called only on Honeycomb and later |
| @Override |
| public void onBuildHeaders(List<Header> target) { |
| loadHeadersFromResource(R.xml.preference_headers, target); |
| } |
| </pre> |
| |
| <p>The only thing left to do is handle the {@link android.content.Intent} that's passed into the |
| activity to identify which preference file to load. So retrieve the intent's action and compare it |
| to known action strings that you've used in the preference XML's {@code <intent>} tags:</p> |
| |
| <pre> |
| final static String ACTION_PREFS_ONE = "com.example.prefs.PREFS_ONE"; |
| ... |
| |
| @Override |
| public void onCreate(Bundle savedInstanceState) { |
| super.onCreate(savedInstanceState); |
| |
| String action = getIntent().getAction(); |
| if (action != null && action.equals(ACTION_PREFS_ONE)) { |
| addPreferencesFromResource(R.xml.preferences); |
| } |
| ... |
| |
| else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { |
| // Load the legacy preferences headers |
| addPreferencesFromResource(R.xml.preference_headers_legacy); |
| } |
| } |
| </pre> |
| |
| <p>Beware that consecutive calls to {@link |
| android.preference.PreferenceActivity#addPreferencesFromResource addPreferencesFromResource()} will |
| stack all the preferences in a single list, so be sure that it's only called once by chaining the |
| conditions with else-if statements.</p> |
| |
| |
| |
| |
| |
| <h2 id="ReadingPrefs">Reading Preferences</h2> |
| |
| <p>By default, all your app's preferences are saved to a file that's accessible from anywhere |
| within your application by calling the static method {@link |
| android.preference.PreferenceManager#getDefaultSharedPreferences |
| PreferenceManager.getDefaultSharedPreferences()}. This returns the {@link |
| android.content.SharedPreferences} object containing all the key-value pairs that are associated |
| with the {@link android.preference.Preference} objects used in your {@link |
| android.preference.PreferenceActivity}.</p> |
| |
| <p>For example, here's how you can read one of the preference values from any other activity in your |
| application:</p> |
| |
| <pre> |
| SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this); |
| String syncConnPref = sharedPref.getString(SettingsActivity.KEY_PREF_SYNC_CONN, ""); |
| </pre> |
| |
| |
| |
| <h3 id="Listening">Listening for preference changes</h3> |
| |
| <p>There are several reasons you might want to be notified as soon as the use changes one of the |
| preferences. In order to receive a callback when a change happens to any one of the preferences, |
| implement the {@link android.content.SharedPreferences.OnSharedPreferenceChangeListener |
| SharedPreference.OnSharedPreferenceChangeListener} interface and register the listener for the |
| {@link android.content.SharedPreferences} object by calling {@link |
| android.content.SharedPreferences#registerOnSharedPreferenceChangeListener |
| registerOnSharedPreferenceChangeListener()}.</p> |
| |
| <p>The interface has only one callback method, {@link |
| android.content.SharedPreferences.OnSharedPreferenceChangeListener#onSharedPreferenceChanged |
| onSharedPreferenceChanged()}, and you might find it easiest to implement the interface as a part of |
| your activity. For example:</p> |
| |
| <pre> |
| public class SettingsActivity extends PreferenceActivity |
| implements OnSharedPreferenceChangeListener { |
| public static final String KEY_PREF_SYNC_CONN = "pref_syncConnectionType"; |
| ... |
| |
| public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, |
| String key) { |
| if (key.equals(KEY_PREF_SYNC_CONN)) { |
| Preference connectionPref = findPreference(key); |
| // Set summary to be the user-description for the selected value |
| connectionPref.setSummary(sharedPreferences.getString(key, "")); |
| } |
| } |
| } |
| </pre> |
| |
| <p>In this example, the method checks whether the changed setting is for a known preference key. It |
| calls {@link android.preference.PreferenceActivity#findPreference findPreference()} to get the |
| {@link android.preference.Preference} object that was changed so it can modify the item's |
| summary to be a description of the user's selection. That is, when the setting is a {@link |
| android.preference.ListPreference} or other multiple choice setting, you should call {@link |
| android.preference.Preference#setSummary setSummary()} when the setting changes to display the |
| current status (such as the Sleep setting shown in figure 5).</p> |
| |
| <p class="note"><strong>Note:</strong> As described in the Android Design document about <a |
| href="{@docRoot}design/patterns/settings.html">Settings</a>, we recommend that you update the |
| summary for a {@link android.preference.ListPreference} each time the user changes the preference in |
| order to describe the current setting.</p> |
| |
| <p>For proper lifecycle management in the activity, we recommend that you register and unregister |
| your {@link android.content.SharedPreferences.OnSharedPreferenceChangeListener} during the {@link |
| android.app.Activity#onResume} and {@link android.app.Activity#onPause} callbacks, respectively:</p> |
| |
| <pre> |
| @Override |
| protected void onResume() { |
| super.onResume(); |
| getPreferenceScreen().getSharedPreferences() |
| .registerOnSharedPreferenceChangeListener(this); |
| } |
| |
| @Override |
| protected void onPause() { |
| super.onPause(); |
| getPreferenceScreen().getSharedPreferences() |
| .unregisterOnSharedPreferenceChangeListener(this); |
| } |
| </pre> |
| |
| <p class="caution"><strong>Caution:</strong> When you call {@link |
| android.content.SharedPreferences#registerOnSharedPreferenceChangeListener |
| registerOnSharedPreferenceChangeListener()}, the preference manager does not |
| currently store a strong reference to the listener. You must store a strong |
| reference to the listener, or it will be susceptible to garbage collection. We |
| recommend you keep a reference to the listener in the instance data of an object |
| that will exist as long as you need the listener.</p> |
| |
| <p>For example, in the following code, the caller does not keep a reference to |
| the listener. As a result, the listener will be subject to garbage collection, |
| and it will fail at some indeterminate time in the future:</p> |
| |
| <pre> |
| prefs.registerOnSharedPreferenceChangeListener( |
| // Bad! The listener is subject to garbage collection! |
| new SharedPreferences.OnSharedPreferenceChangeListener() { |
| public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { |
| // listener implementation |
| } |
| }); |
| </pre> |
| |
| <p>Instead, store a reference to the listener in an instance data field of an |
| object that will exist as long as the listener is needed:</p> |
| |
| <pre> |
| SharedPreferences.OnSharedPreferenceChangeListener listener = |
| new SharedPreferences.OnSharedPreferenceChangeListener() { |
| public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { |
| // listener implementation |
| } |
| }; |
| prefs.registerOnSharedPreferenceChangeListener(listener); |
| </pre> |
| |
| <h2 id="NetworkUsage">Managing Network Usage</h2> |
| |
| |
| <p>Beginning with Android 4.0, the system's Settings application allows users to see how much |
| network data their applications are using while in the foreground and background. Users can then |
| disable the use of background data for individual apps. In order to avoid users disabling your app's |
| access to data from the background, you should use the data connection efficiently and allow |
| users to refine your app's data usage through your application settings.<p> |
| |
| <p>For example, you might allow the user to control how often your app syncs data, whether your app |
| performs uploads/downloads only when on Wi-Fi, whether your app uses data while roaming, etc. With |
| these controls available to them, users are much less likely to disable your app's access to data |
| when they approach the limits they set in the system Settings, because they can instead precisely |
| control how much data your app uses.</p> |
| |
| <p>Once you've added the necessary preferences in your {@link android.preference.PreferenceActivity} |
| to control your app's data habits, you should add an intent filter for {@link |
| android.content.Intent#ACTION_MANAGE_NETWORK_USAGE} in your manifest file. For example:</p> |
| |
| <pre> |
| <activity android:name="SettingsActivity" ... > |
| <intent-filter> |
| <action android:name="android.intent.action.MANAGE_NETWORK_USAGE" /> |
| <category android:name="android.intent.category.DEFAULT" /> |
| </intent-filter> |
| </activity> |
| </pre> |
| |
| <p>This intent filter indicates to the system that this is the activity that controls your |
| application's data usage. Thus, when the user inspects how much data your app is using from the |
| system's Settings app, a <em>View application settings</em> button is available that launches your |
| {@link android.preference.PreferenceActivity} so the user can refine how much data your app |
| uses.</p> |
| |
| |
| |
| |
| |
| |
| |
| <h2 id="Custom">Building a Custom Preference</h2> |
| |
| <p>The Android framework includes a variety of {@link android.preference.Preference} subclasses that |
| allow you to build a UI for several different types of settings. |
| However, you might discover a setting you need for which there’s no built-in solution, such as a |
| number picker or date picker. In such a case, you’ll need to create a custom preference by extending |
| the {@link android.preference.Preference} class or one of the other subclasses.</p> |
| |
| <p>When you extend the {@link android.preference.Preference} class, there are a few important |
| things you need to do:</p> |
| |
| <ul> |
| <li>Specify the user interface that appears when the user selects the settings.</li> |
| <li>Save the setting's value when appropriate.</li> |
| <li>Initialize the {@link android.preference.Preference} with the current (or default) value |
| when it comes into view.</li> |
| <li>Provide the default value when requested by the system.</li> |
| <li>If the {@link android.preference.Preference} provides its own UI (such as a dialog), save |
| and restore the state to handle lifecycle changes (such as when the user rotates the screen).</li> |
| </ul> |
| |
| <p>The following sections describe how to accomplish each of these tasks.</p> |
| |
| |
| |
| <h3 id="CustomSelected">Specifying the user interface</h3> |
| |
| <p>If you directly extend the {@link android.preference.Preference} class, you need to implement |
| {@link android.preference.Preference#onClick()} to define the action that occurs when the user |
| selects the item. However, most custom settings extend {@link android.preference.DialogPreference} to |
| show a dialog, which simplifies the procedure. When you extend {@link |
| android.preference.DialogPreference}, you must call {@link |
| android.preference.DialogPreference#setDialogLayoutResource setDialogLayoutResourcs()} during in the |
| class constructor to specify the layout for the dialog.</p> |
| |
| <p>For example, here's the constructor for a custom {@link |
| android.preference.DialogPreference} that declares the layout and specifies the text for the |
| default positive and negative dialog buttons:</p> |
| |
| <pre> |
| public class NumberPickerPreference extends DialogPreference { |
| public NumberPickerPreference(Context context, AttributeSet attrs) { |
| super(context, attrs); |
| |
| setDialogLayoutResource(R.layout.numberpicker_dialog); |
| setPositiveButtonText(android.R.string.ok); |
| setNegativeButtonText(android.R.string.cancel); |
| |
| setDialogIcon(null); |
| } |
| ... |
| } |
| </pre> |
| |
| |
| |
| <h3 id="CustomSave">Saving the setting's value</h3> |
| |
| <p>You can save a value for the setting at any time by calling one of the {@link |
| android.preference.Preference} class's {@code persist*()} methods, such as {@link |
| android.preference.Preference#persistInt persistInt()} if the setting's value is an integer or |
| {@link android.preference.Preference#persistBoolean persistBoolean()} to save a boolean.</p> |
| |
| <p class="note"><strong>Note:</strong> Each {@link android.preference.Preference} can save only one |
| data type, so you must use the {@code persist*()} method appropriate for the data type used by your |
| custom {@link android.preference.Preference}.</p> |
| |
| <p>When you choose to persist the setting can depend on which {@link |
| android.preference.Preference} class you extend. If you extend {@link |
| android.preference.DialogPreference}, then you should persist the value only when the dialog |
| closes due to a positive result (the user selects the "OK" button).</p> |
| |
| <p>When a {@link android.preference.DialogPreference} closes, the system calls the {@link |
| android.preference.DialogPreference#onDialogClosed onDialogClosed()} method. The method includes a |
| boolean argument that specifies whether the user result is "positive"—if the value is |
| <code>true</code>, then the user selected the positive button and you should save the new value. For |
| example:</p> |
| |
| <pre> |
| @Override |
| protected void onDialogClosed(boolean positiveResult) { |
| // When the user selects "OK", persist the new value |
| if (positiveResult) { |
| persistInt(mNewValue); |
| } |
| } |
| </pre> |
| |
| <p>In this example, <code>mNewValue</code> is a class member that holds the setting's current |
| value. Calling {@link android.preference.Preference#persistInt persistInt()} saves the value to |
| the {@link android.content.SharedPreferences} file (automatically using the key that's |
| specified in the XML file for this {@link android.preference.Preference}).</p> |
| |
| |
| <h3 id="CustomInitialize">Initializing the current value</h3> |
| |
| <p>When the system adds your {@link android.preference.Preference} to the screen, it |
| calls {@link android.preference.Preference#onSetInitialValue onSetInitialValue()} to notify |
| you whether the setting has a persisted value. If there is no persisted value, this call provides |
| you the default value.</p> |
| |
| <p>The {@link android.preference.Preference#onSetInitialValue onSetInitialValue()} method passes |
| a boolean, <code>restorePersistedValue</code>, to indicate whether a value has already been persisted |
| for the setting. If it is <code>true</code>, then you should retrieve the persisted value by calling |
| one of the {@link |
| android.preference.Preference} class's {@code getPersisted*()} methods, such as {@link |
| android.preference.Preference#getPersistedInt getPersistedInt()} for an integer value. You'll |
| usually want to retrieve the persisted value so you can properly update the UI to reflect the |
| previously saved value.</p> |
| |
| <p>If <code>restorePersistedValue</code> is <code>false</code>, then you |
| should use the default value that is passed in the second argument.</p> |
| |
| <pre> |
| @Override |
| protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) { |
| if (restorePersistedValue) { |
| // Restore existing state |
| mCurrentValue = this.getPersistedInt(DEFAULT_VALUE); |
| } else { |
| // Set default state from the XML attribute |
| mCurrentValue = (Integer) defaultValue; |
| persistInt(mCurrentValue); |
| } |
| } |
| </pre> |
| |
| <p>Each {@code getPersisted*()} method takes an argument that specifies the |
| default value to use in case there is actually no persisted value or the key does not exist. In |
| the example above, a local constant is used to specify the default value in case {@link |
| android.preference.Preference#getPersistedInt getPersistedInt()} can't return a persisted value.</p> |
| |
| <p class="caution"><strong>Caution:</strong> You <strong>cannot</strong> use the |
| <code>defaultValue</code> as the default value in the {@code getPersisted*()} method, because |
| its value is always null when <code>restorePersistedValue</code> is <code>true</code>.</p> |
| |
| |
| <h3 id="CustomDefault">Providing a default value</h3> |
| |
| <p>If the instance of your {@link android.preference.Preference} class specifies a default value |
| (with the {@code android:defaultValue} attribute), then the |
| system calls {@link android.preference.Preference#onGetDefaultValue |
| onGetDefaultValue()} when it instantiates the object in order to retrieve the value. You must |
| implement this method in order for the system to save the default value in the {@link |
| android.content.SharedPreferences}. For example:</p> |
| |
| <pre> |
| @Override |
| protected Object onGetDefaultValue(TypedArray a, int index) { |
| return a.getInteger(index, DEFAULT_VALUE); |
| } |
| </pre> |
| |
| <p>The method arguments provide everything you need: the array of attributes and the index |
| position of the {@code android:defaultValue}, which you must retrieve. The reason you must |
| implement this method to extract the default value from the attribute is because you must specify |
| a local default value for the attribute in case the value is undefined.</p> |
| |
| |
| |
| <h3 id="CustomSaveState">Saving and restoring the Preference's state</h3> |
| |
| <p>Just like a {@link android.view.View} in a layout, your {@link android.preference.Preference} |
| subclass is responsible for saving and restoring its state in case the activity or fragment is |
| restarted (such as when the user rotates the screen). To properly save and |
| restore the state of your {@link android.preference.Preference} class, you must implement the |
| lifecycle callback methods {@link android.preference.Preference#onSaveInstanceState |
| onSaveInstanceState()} and {@link |
| android.preference.Preference#onRestoreInstanceState onRestoreInstanceState()}.</p> |
| |
| <p>The state of your {@link android.preference.Preference} is defined by an object that implements |
| the {@link android.os.Parcelable} interface. The Android framework provides such an object for you |
| as a starting point to define your state object: the {@link |
| android.preference.Preference.BaseSavedState} class.</p> |
| |
| <p>To define how your {@link android.preference.Preference} class saves its state, you should |
| extend the {@link android.preference.Preference.BaseSavedState} class. You need to override just |
| a few methods and define the {@link android.preference.Preference.BaseSavedState#CREATOR} |
| object.</p> |
| |
| <p>For most apps, you can copy the following implementation and simply change the lines that |
| handle the {@code value} if your {@link android.preference.Preference} subclass saves a data |
| type other than an integer.</p> |
| |
| <pre> |
| private static class SavedState extends BaseSavedState { |
| // Member that holds the setting's value |
| // Change this data type to match the type saved by your Preference |
| int value; |
| |
| public SavedState(Parcelable superState) { |
| super(superState); |
| } |
| |
| public SavedState(Parcel source) { |
| super(source); |
| // Get the current preference's value |
| value = source.readInt(); // Change this to read the appropriate data type |
| } |
| |
| @Override |
| public void writeToParcel(Parcel dest, int flags) { |
| super.writeToParcel(dest, flags); |
| // Write the preference's value |
| dest.writeInt(value); // Change this to write the appropriate data type |
| } |
| |
| // Standard creator object using an instance of this class |
| public static final Parcelable.Creator<SavedState> CREATOR = |
| new Parcelable.Creator<SavedState>() { |
| |
| public SavedState createFromParcel(Parcel in) { |
| return new SavedState(in); |
| } |
| |
| public SavedState[] newArray(int size) { |
| return new SavedState[size]; |
| } |
| }; |
| } |
| </pre> |
| |
| <p>With the above implementation of {@link android.preference.Preference.BaseSavedState} added |
| to your app (usually as a subclass of your {@link android.preference.Preference} subclass), you |
| then need to implement the {@link android.preference.Preference#onSaveInstanceState |
| onSaveInstanceState()} and {@link |
| android.preference.Preference#onRestoreInstanceState onRestoreInstanceState()} methods for your |
| {@link android.preference.Preference} subclass.</p> |
| |
| <p>For example:</p> |
| |
| <pre> |
| @Override |
| protected Parcelable onSaveInstanceState() { |
| final Parcelable superState = super.onSaveInstanceState(); |
| // Check whether this Preference is persistent (continually saved) |
| if (isPersistent()) { |
| // No need to save instance state since it's persistent, |
| // use superclass state |
| return superState; |
| } |
| |
| // Create instance of custom BaseSavedState |
| final SavedState myState = new SavedState(superState); |
| // Set the state's value with the class member that holds current |
| // setting value |
| myState.value = mNewValue; |
| return myState; |
| } |
| |
| @Override |
| protected void onRestoreInstanceState(Parcelable state) { |
| // Check whether we saved the state in onSaveInstanceState |
| if (state == null || !state.getClass().equals(SavedState.class)) { |
| // Didn't save the state, so call superclass |
| super.onRestoreInstanceState(state); |
| return; |
| } |
| |
| // Cast state to custom BaseSavedState and pass to superclass |
| SavedState myState = (SavedState) state; |
| super.onRestoreInstanceState(myState.getSuperState()); |
| |
| // Set this Preference's widget to reflect the restored state |
| mNumberPicker.setValue(myState.value); |
| } |
| </pre> |
| |