PreferenceFragment.java revision 35d7b89b9f6151083001e3bae315a8e98882741f
1b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* 2b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * Copyright (C) 2010 The Android Open Source Project 3b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * 4b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * Licensed under the Apache License, Version 2.0 (the "License"); 5b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * you may not use this file except in compliance with the License. 6b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * You may obtain a copy of the License at 7b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * 8b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * http://www.apache.org/licenses/LICENSE-2.0 9b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * 10b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * Unless required by applicable law or agreed to in writing, software 11b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * distributed under the License is distributed on an "AS IS" BASIS, 12b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * See the License for the specific language governing permissions and 14b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * limitations under the License. 15b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */ 16b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 17b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovpackage android.preference; 18b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 19b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovimport android.app.Activity; 20b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovimport android.app.Fragment; 21b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovimport android.content.Intent; 22b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovimport android.content.SharedPreferences; 23b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovimport android.os.Bundle; 24b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovimport android.os.Handler; 25b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovimport android.os.Message; 26b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovimport android.view.KeyEvent; 27b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovimport android.view.LayoutInflater; 28b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovimport android.view.View; 29b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovimport android.view.ViewGroup; 30436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovimport android.view.View.OnKeyListener; 31436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovimport android.widget.ListView; 32436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 33436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/** 34eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov * Shows a hierarchy of {@link Preference} objects as 35eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov * lists. These preferences will 36b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * automatically save to {@link SharedPreferences} as the user interacts with 37b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * them. To retrieve an instance of {@link SharedPreferences} that the 38b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * preference hierarchy in this fragment will use, call 39b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * {@link PreferenceManager#getDefaultSharedPreferences(android.content.Context)} 40b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * with a context in the same package as this fragment. 41b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * <p> 42b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * Furthermore, the preferences shown will follow the visual style of system 43663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng * preferences. It is easy to create a hierarchy of preferences (that can be 44b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * shown on multiple screens) via XML. For these reasons, it is recommended to 45b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * use this fragment (as a superclass) to deal with preferences in applications. 46b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * <p> 47663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng * A {@link PreferenceScreen} object should be at the top of the preference 48b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * hierarchy. Furthermore, subsequent {@link PreferenceScreen} in the hierarchy 49663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng * denote a screen break--that is the preferences contained within subsequent 50663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng * {@link PreferenceScreen} should be shown on another screen. The preference 51663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng * framework handles showing these other screens from the preference hierarchy. 52b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * <p> 53663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng * The preference hierarchy can be formed in multiple ways: 54b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * <li> From an XML file specifying the hierarchy 55b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * <li> From different {@link Activity Activities} that each specify its own 56b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * preferences in an XML file via {@link Activity} meta-data 57b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * <li> From an object hierarchy rooted with {@link PreferenceScreen} 58b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * <p> 59b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * To inflate from XML, use the {@link #addPreferencesFromResource(int)}. The 60b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * root element should be a {@link PreferenceScreen}. Subsequent elements can point 61436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * to actual {@link Preference} subclasses. As mentioned above, subsequent 62b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * {@link PreferenceScreen} in the hierarchy will result in the screen break. 63b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * <p> 64b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * To specify an {@link Intent} to query {@link Activity Activities} that each 65b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * have preferences, use {@link #addPreferencesFromIntent}. Each 66b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * {@link Activity} can specify meta-data in the manifest (via the key 67b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * {@link PreferenceManager#METADATA_KEY_PREFERENCES}) that points to an XML 68b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * resource. These XML resources will be inflated into a single preference 69b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * hierarchy and shown by this fragment. 70b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * <p> 71b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * To specify an object hierarchy rooted with {@link PreferenceScreen}, use 72b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * {@link #setPreferenceScreen(PreferenceScreen)}. 73b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * <p> 74b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * As a convenience, this fragment implements a click listener for any 75b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * preference in the current hierarchy, see 76b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * {@link #onPreferenceTreeClick(PreferenceScreen, Preference)}. 77b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * 78b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * <div class="special reference"> 79b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * <h3>Developer Guides</h3> 80b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * <p>For information about using {@code PreferenceFragment}, 81b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * read the <a href="{@docRoot}guide/topics/ui/settings.html">Settings</a> 82b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * guide.</p> 83b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * </div> 84b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * 85b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * <a name="SampleCode"></a> 86b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * <h3>Sample Code</h3> 87b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * 88b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * <p>The following sample code shows a simple preference fragment that is 89b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * populated from a resource. The resource it loads is:</p> 90b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * 91b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * {@sample development/samples/ApiDemos/res/xml/preferences.xml preferences} 92b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * 93b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * <p>The fragment implementation itself simply populates the preferences 94b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * when created. Note that the preferences framework takes care of loading 95b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * the current values out of the app preferences and writing them when changed:</p> 96b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * 97b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * {@sample development/samples/ApiDemos/src/com/example/android/apis/preference/FragmentPreferences.java 98b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * fragment} 99b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * 100b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * @see Preference 101b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * @see PreferenceScreen 102b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */ 103436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovpublic abstract class PreferenceFragment extends Fragment implements 104b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov PreferenceManager.OnPreferenceTreeClickListener { 105b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 106b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov private static final String PREFERENCES_TAG = "android:preferences"; 107b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 108b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov private PreferenceManager mPreferenceManager; 109b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov private ListView mList; 110b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov private boolean mHavePrefs; 111b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov private boolean mInitDone; 112b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 113436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /** 114436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * The starting request code given out to preference framework. 115436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov */ 116436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov private static final int FIRST_REQUEST_CODE = 100; 117436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 118436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov private static final int MSG_BIND_PREFERENCES = 1; 119436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov private Handler mHandler = new Handler() { 120b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov @Override 121436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov public void handleMessage(Message msg) { 122b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov switch (msg.what) { 123b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 124b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case MSG_BIND_PREFERENCES: 125b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov bindPreferences(); 126b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov break; 127436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 128436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 129436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov }; 130436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 131436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov final private Runnable mRequestFocus = new Runnable() { 132436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov public void run() { 133436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov mList.focusableViewAvailable(mList); 134436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 135436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov }; 136436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 137436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /** 138436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * Interface that PreferenceFragment's containing activity should 139436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * implement to be able to process preference items that wish to 140436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * switch to a new fragment. 141436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov */ 142436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov public interface OnPreferenceStartFragmentCallback { 143436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /** 144436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * Called when the user has clicked on a Preference that has 145436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * a fragment class name associated with it. The implementation 146436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * to should instantiate and switch to an instance of the given 147436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * fragment. 148436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov */ 149436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref); 150436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 151436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 152eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov @Override 153eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov public void onCreate(Bundle savedInstanceState) { 154eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov super.onCreate(savedInstanceState); 155eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov mPreferenceManager = new PreferenceManager(getActivity(), FIRST_REQUEST_CODE); 156eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov mPreferenceManager.setFragment(this); 157eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov } 158eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 159eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov @Override 160eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov public View onCreateView(LayoutInflater inflater, ViewGroup container, 161eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov Bundle savedInstanceState) { 162eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov return inflater.inflate(com.android.internal.R.layout.preference_list_fragment, container, 163eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov false); 164eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov } 165eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 166eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov @Override 167eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov public void onActivityCreated(Bundle savedInstanceState) { 168eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov super.onActivityCreated(savedInstanceState); 169eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 170eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov if (mHavePrefs) { 171eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov bindPreferences(); 172eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov } 173eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 174eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov mInitDone = true; 175eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 176b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (savedInstanceState != null) { 177b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Bundle container = savedInstanceState.getBundle(PREFERENCES_TAG); 178b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (container != null) { 179b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov final PreferenceScreen preferenceScreen = getPreferenceScreen(); 180b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (preferenceScreen != null) { 181b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov preferenceScreen.restoreHierarchyState(container); 182b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 183b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 184436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 185b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 186b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 187b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov @Override 188436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov public void onStart() { 189436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov super.onStart(); 190436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov mPreferenceManager.setOnPreferenceTreeClickListener(this); 191b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 192b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 193b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov @Override 194b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov public void onStop() { 195b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov super.onStop(); 196b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mPreferenceManager.dispatchActivityStop(); 197b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mPreferenceManager.setOnPreferenceTreeClickListener(null); 198b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 199b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 200b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov @Override 201436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov public void onDestroyView() { 202436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov mList = null; 203b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mHandler.removeCallbacks(mRequestFocus); 204b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mHandler.removeMessages(MSG_BIND_PREFERENCES); 205b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov super.onDestroyView(); 206b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 207b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 208b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov @Override 209b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov public void onDestroy() { 210b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov super.onDestroy(); 211b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mPreferenceManager.dispatchActivityDestroy(); 212b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 213b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 214b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov @Override 215b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov public void onSaveInstanceState(Bundle outState) { 216b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov super.onSaveInstanceState(outState); 217b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 218b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov final PreferenceScreen preferenceScreen = getPreferenceScreen(); 219b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (preferenceScreen != null) { 220b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Bundle container = new Bundle(); 221b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov preferenceScreen.saveHierarchyState(container); 222b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov outState.putBundle(PREFERENCES_TAG, container); 223b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 224b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 225436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 226b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov @Override 227b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov public void onActivityResult(int requestCode, int resultCode, Intent data) { 228b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov super.onActivityResult(requestCode, resultCode, data); 229eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 230436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov mPreferenceManager.dispatchActivityResult(requestCode, resultCode, data); 231436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 232b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 233b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /** 234b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * Returns the {@link PreferenceManager} used by this fragment. 235b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * @return The {@link PreferenceManager}. 236436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov */ 237b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov public PreferenceManager getPreferenceManager() { 238b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return mPreferenceManager; 239b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 240436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 241b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /** 242663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng * Sets the root of the preference hierarchy that this fragment is showing. 243663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng * 244436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * @param preferenceScreen The root {@link PreferenceScreen} of the preference hierarchy. 245b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */ 246436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov public void setPreferenceScreen(PreferenceScreen preferenceScreen) { 247b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (mPreferenceManager.setPreferences(preferenceScreen) && preferenceScreen != null) { 248eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov mHavePrefs = true; 249eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov if (mInitDone) { 250b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov postBindPreferences(); 251b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 252b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 253b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 254b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 255b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /** 256b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * Gets the root of the preference hierarchy that this fragment is showing. 257b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * 258b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * @return The {@link PreferenceScreen} that is the root of the preference 259436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * hierarchy. 260eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov */ 261b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov public PreferenceScreen getPreferenceScreen() { 262b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return mPreferenceManager.getPreferenceScreen(); 263b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 264b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 265b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /** 266b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * Adds preferences from activities that match the given {@link Intent}. 267436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * 268b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * @param intent The {@link Intent} to query activities. 269b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */ 270b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov public void addPreferencesFromIntent(Intent intent) { 271b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov requirePreferenceManager(); 272b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 273436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov setPreferenceScreen(mPreferenceManager.inflateFromIntent(intent, getPreferenceScreen())); 274436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 275436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 276b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /** 277b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * Inflates the given XML resource and adds the preference hierarchy to the current 278b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * preference hierarchy. 279b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * 280436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * @param preferencesResId The XML resource ID to inflate. 281b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */ 282b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov public void addPreferencesFromResource(int preferencesResId) { 283b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov requirePreferenceManager(); 284436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 285b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov setPreferenceScreen(mPreferenceManager.inflateFromResource(getActivity(), 286b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov preferencesResId, getPreferenceScreen())); 287436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 288436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 289436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /** 290436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * {@inheritDoc} 291436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov */ 292b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, 293b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Preference preference) { 294b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (preference.getFragment() != null && 295b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov getActivity() instanceof OnPreferenceStartFragmentCallback) { 296436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return ((OnPreferenceStartFragmentCallback)getActivity()).onPreferenceStartFragment( 297b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov this, preference); 298b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 299b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return false; 300b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 301436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 302b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /** 303b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * Finds a {@link Preference} based on its key. 304b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * 305b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * @param key The key of the preference to retrieve. 306436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * @return The {@link Preference} with the key, or null. 307b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * @see PreferenceGroup#findPreference(CharSequence) 308b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */ 309b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov public Preference findPreference(CharSequence key) { 310b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (mPreferenceManager == null) { 311b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return null; 312eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov } 313eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov return mPreferenceManager.findPreference(key); 314eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov } 315eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 316eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov private void requirePreferenceManager() { 317eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov if (mPreferenceManager == null) { 318eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov throw new RuntimeException("This should be called after super.onCreate."); 319eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov } 320eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov } 321eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 322eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov private void postBindPreferences() { 323eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov if (mHandler.hasMessages(MSG_BIND_PREFERENCES)) return; 324eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov mHandler.obtainMessage(MSG_BIND_PREFERENCES).sendToTarget(); 325eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov } 326eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 327eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov private void bindPreferences() { 328eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov final PreferenceScreen preferenceScreen = getPreferenceScreen(); 329eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov if (preferenceScreen != null) { 330eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov preferenceScreen.bind(getListView()); 331eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov } 332eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov } 333eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 334eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov /** @hide */ 335eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov public ListView getListView() { 336eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov ensureList(); 337eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov return mList; 338b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 339b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 340b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /** @hide */ 341b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov public boolean hasListView() { 342b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (mList != null) { 343b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return true; 344b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 345b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov View root = getView(); 346b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (root == null) { 347eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov return false; 348b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 349b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov View rawListView = root.findViewById(android.R.id.list); 350b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (!(rawListView instanceof ListView)) { 351b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return false; 352b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 353b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mList = (ListView)rawListView; 354b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (mList == null) { 355b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return false; 356b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 357436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return true; 358436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 359436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 360436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov private void ensureList() { 361436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (mList != null) { 362b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return; 363b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 364b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov View root = getView(); 365b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (root == null) { 366b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov throw new IllegalStateException("Content view not yet created"); 367b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 368b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov View rawListView = root.findViewById(android.R.id.list); 369b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (!(rawListView instanceof ListView)) { 370436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov throw new RuntimeException( 371436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "Content has view with id attribute 'android.R.id.list' " 372b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov + "that is not a ListView class"); 373b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 374b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mList = (ListView)rawListView; 375663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (mList == null) { 376663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng throw new RuntimeException( 377663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng "Your content must have a ListView whose id attribute is " + 378663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng "'android.R.id.list'"); 379663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 380663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng mList.setOnKeyListener(mListOnKeyListener); 381663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng mHandler.post(mRequestFocus); 382663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 383663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 384663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng private OnKeyListener mListOnKeyListener = new OnKeyListener() { 385663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 386663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng @Override 387b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov public boolean onKey(View v, int keyCode, KeyEvent event) { 388b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Object selectedItem = mList.getSelectedItem(); 389b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (selectedItem instanceof Preference) { 390eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov View selectedView = mList.getSelectedView(); 391eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov return ((Preference)selectedItem).onKey( 392eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov selectedView, keyCode, event); 393b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 394b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return false; 395436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 396eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 397eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov }; 398436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 399436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov