• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.preference;
18 
19 import android.app.Activity;
20 import android.app.ListActivity;
21 import android.content.Intent;
22 import android.content.SharedPreferences;
23 import android.os.Bundle;
24 import android.os.Handler;
25 import android.os.Message;
26 import android.view.View;
27 import android.view.Window;
28 
29 /**
30  * Shows a hierarchy of {@link Preference} objects as
31  * lists, possibly spanning multiple screens. These preferences will
32  * automatically save to {@link SharedPreferences} as the user interacts with
33  * them. To retrieve an instance of {@link SharedPreferences} that the
34  * preference hierarchy in this activity will use, call
35  * {@link PreferenceManager#getDefaultSharedPreferences(android.content.Context)}
36  * with a context in the same package as this activity.
37  * <p>
38  * Furthermore, the preferences shown will follow the visual style of system
39  * preferences. It is easy to create a hierarchy of preferences (that can be
40  * shown on multiple screens) via XML. For these reasons, it is recommended to
41  * use this activity (as a superclass) to deal with preferences in applications.
42  * <p>
43  * A {@link PreferenceScreen} object should be at the top of the preference
44  * hierarchy. Furthermore, subsequent {@link PreferenceScreen} in the hierarchy
45  * denote a screen break--that is the preferences contained within subsequent
46  * {@link PreferenceScreen} should be shown on another screen. The preference
47  * framework handles showing these other screens from the preference hierarchy.
48  * <p>
49  * The preference hierarchy can be formed in multiple ways:
50  * <li> From an XML file specifying the hierarchy
51  * <li> From different {@link Activity Activities} that each specify its own
52  * preferences in an XML file via {@link Activity} meta-data
53  * <li> From an object hierarchy rooted with {@link PreferenceScreen}
54  * <p>
55  * To inflate from XML, use the {@link #addPreferencesFromResource(int)}. The
56  * root element should be a {@link PreferenceScreen}. Subsequent elements can point
57  * to actual {@link Preference} subclasses. As mentioned above, subsequent
58  * {@link PreferenceScreen} in the hierarchy will result in the screen break.
59  * <p>
60  * To specify an {@link Intent} to query {@link Activity Activities} that each
61  * have preferences, use {@link #addPreferencesFromIntent}. Each
62  * {@link Activity} can specify meta-data in the manifest (via the key
63  * {@link PreferenceManager#METADATA_KEY_PREFERENCES}) that points to an XML
64  * resource. These XML resources will be inflated into a single preference
65  * hierarchy and shown by this activity.
66  * <p>
67  * To specify an object hierarchy rooted with {@link PreferenceScreen}, use
68  * {@link #setPreferenceScreen(PreferenceScreen)}.
69  * <p>
70  * As a convenience, this activity implements a click listener for any
71  * preference in the current hierarchy, see
72  * {@link #onPreferenceTreeClick(PreferenceScreen, Preference)}.
73  *
74  * @see Preference
75  * @see PreferenceScreen
76  */
77 public abstract class PreferenceActivity extends ListActivity implements
78         PreferenceManager.OnPreferenceTreeClickListener {
79 
80     private static final String PREFERENCES_TAG = "android:preferences";
81 
82     private PreferenceManager mPreferenceManager;
83 
84     /**
85      * The starting request code given out to preference framework.
86      */
87     private static final int FIRST_REQUEST_CODE = 100;
88 
89     private static final int MSG_BIND_PREFERENCES = 0;
90     private Handler mHandler = new Handler() {
91         @Override
92         public void handleMessage(Message msg) {
93             switch (msg.what) {
94 
95                 case MSG_BIND_PREFERENCES:
96                     bindPreferences();
97                     break;
98             }
99         }
100     };
101 
102     @Override
onCreate(Bundle savedInstanceState)103     protected void onCreate(Bundle savedInstanceState) {
104         super.onCreate(savedInstanceState);
105 
106         setContentView(com.android.internal.R.layout.preference_list_content);
107 
108         mPreferenceManager = onCreatePreferenceManager();
109         getListView().setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
110     }
111 
112     @Override
onStop()113     protected void onStop() {
114         super.onStop();
115 
116         mPreferenceManager.dispatchActivityStop();
117     }
118 
119     @Override
onDestroy()120     protected void onDestroy() {
121         super.onDestroy();
122 
123         mPreferenceManager.dispatchActivityDestroy();
124     }
125 
126     @Override
onSaveInstanceState(Bundle outState)127     protected void onSaveInstanceState(Bundle outState) {
128         super.onSaveInstanceState(outState);
129 
130         final PreferenceScreen preferenceScreen = getPreferenceScreen();
131         if (preferenceScreen != null) {
132             Bundle container = new Bundle();
133             preferenceScreen.saveHierarchyState(container);
134             outState.putBundle(PREFERENCES_TAG, container);
135         }
136     }
137 
138     @Override
onRestoreInstanceState(Bundle state)139     protected void onRestoreInstanceState(Bundle state) {
140         super.onRestoreInstanceState(state);
141 
142         Bundle container = state.getBundle(PREFERENCES_TAG);
143         if (container != null) {
144             final PreferenceScreen preferenceScreen = getPreferenceScreen();
145             if (preferenceScreen != null) {
146                 preferenceScreen.restoreHierarchyState(container);
147             }
148         }
149     }
150 
151     @Override
onActivityResult(int requestCode, int resultCode, Intent data)152     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
153         super.onActivityResult(requestCode, resultCode, data);
154 
155         mPreferenceManager.dispatchActivityResult(requestCode, resultCode, data);
156     }
157 
158     @Override
onContentChanged()159     public void onContentChanged() {
160         super.onContentChanged();
161         postBindPreferences();
162     }
163 
164     /**
165      * Posts a message to bind the preferences to the list view.
166      * <p>
167      * Binding late is preferred as any custom preference types created in
168      * {@link #onCreate(Bundle)} are able to have their views recycled.
169      */
postBindPreferences()170     private void postBindPreferences() {
171         if (mHandler.hasMessages(MSG_BIND_PREFERENCES)) return;
172         mHandler.obtainMessage(MSG_BIND_PREFERENCES).sendToTarget();
173     }
174 
bindPreferences()175     private void bindPreferences() {
176         final PreferenceScreen preferenceScreen = getPreferenceScreen();
177         if (preferenceScreen != null) {
178             preferenceScreen.bind(getListView());
179         }
180     }
181 
182     /**
183      * Creates the {@link PreferenceManager}.
184      *
185      * @return The {@link PreferenceManager} used by this activity.
186      */
onCreatePreferenceManager()187     private PreferenceManager onCreatePreferenceManager() {
188         PreferenceManager preferenceManager = new PreferenceManager(this, FIRST_REQUEST_CODE);
189         preferenceManager.setOnPreferenceTreeClickListener(this);
190         return preferenceManager;
191     }
192 
193     /**
194      * Returns the {@link PreferenceManager} used by this activity.
195      * @return The {@link PreferenceManager}.
196      */
getPreferenceManager()197     public PreferenceManager getPreferenceManager() {
198         return mPreferenceManager;
199     }
200 
requirePreferenceManager()201     private void requirePreferenceManager() {
202         if (mPreferenceManager == null) {
203             throw new RuntimeException("This should be called after super.onCreate.");
204         }
205     }
206 
207     /**
208      * Sets the root of the preference hierarchy that this activity is showing.
209      *
210      * @param preferenceScreen The root {@link PreferenceScreen} of the preference hierarchy.
211      */
setPreferenceScreen(PreferenceScreen preferenceScreen)212     public void setPreferenceScreen(PreferenceScreen preferenceScreen) {
213         if (mPreferenceManager.setPreferences(preferenceScreen) && preferenceScreen != null) {
214             postBindPreferences();
215             CharSequence title = getPreferenceScreen().getTitle();
216             // Set the title of the activity
217             if (title != null) {
218                 setTitle(title);
219             }
220         }
221     }
222 
223     /**
224      * Gets the root of the preference hierarchy that this activity is showing.
225      *
226      * @return The {@link PreferenceScreen} that is the root of the preference
227      *         hierarchy.
228      */
getPreferenceScreen()229     public PreferenceScreen getPreferenceScreen() {
230         return mPreferenceManager.getPreferenceScreen();
231     }
232 
233     /**
234      * Adds preferences from activities that match the given {@link Intent}.
235      *
236      * @param intent The {@link Intent} to query activities.
237      */
addPreferencesFromIntent(Intent intent)238     public void addPreferencesFromIntent(Intent intent) {
239         requirePreferenceManager();
240 
241         setPreferenceScreen(mPreferenceManager.inflateFromIntent(intent, getPreferenceScreen()));
242     }
243 
244     /**
245      * Inflates the given XML resource and adds the preference hierarchy to the current
246      * preference hierarchy.
247      *
248      * @param preferencesResId The XML resource ID to inflate.
249      */
addPreferencesFromResource(int preferencesResId)250     public void addPreferencesFromResource(int preferencesResId) {
251         requirePreferenceManager();
252 
253         setPreferenceScreen(mPreferenceManager.inflateFromResource(this, preferencesResId,
254                 getPreferenceScreen()));
255     }
256 
257     /**
258      * {@inheritDoc}
259      */
onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference)260     public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
261         return false;
262     }
263 
264     /**
265      * Finds a {@link Preference} based on its key.
266      *
267      * @param key The key of the preference to retrieve.
268      * @return The {@link Preference} with the key, or null.
269      * @see PreferenceGroup#findPreference(CharSequence)
270      */
findPreference(CharSequence key)271     public Preference findPreference(CharSequence key) {
272 
273         if (mPreferenceManager == null) {
274             return null;
275         }
276 
277         return mPreferenceManager.findPreference(key);
278     }
279 
280     @Override
onNewIntent(Intent intent)281     protected void onNewIntent(Intent intent) {
282         if (mPreferenceManager != null) {
283             mPreferenceManager.dispatchNewIntent(intent);
284         }
285     }
286 
287 }
288