diff options
author | Dianne Hackborn <hackbod@google.com> | 2010-07-28 14:32:15 -0700 |
---|---|---|
committer | Dianne Hackborn <hackbod@google.com> | 2010-07-28 16:06:58 -0700 |
commit | 42c2936f3c6e048caafb17eb9fe91fa4a33c8b86 (patch) | |
tree | dc53aedab5b9bd4868d6d1c7f0141a7b71fd62b1 /core/java/android/preference | |
parent | db4c6ccf224cd512690cc3dcfacccc8acfa71ffd (diff) | |
download | frameworks_base-42c2936f3c6e048caafb17eb9fe91fa4a33c8b86.zip frameworks_base-42c2936f3c6e048caafb17eb9fe91fa4a33c8b86.tar.gz frameworks_base-42c2936f3c6e048caafb17eb9fe91fa4a33c8b86.tar.bz2 |
Add PreferenceFragment.
Change-Id: I9b87ec2c15822cca5b460a9a2d589fc24e21a789
Diffstat (limited to 'core/java/android/preference')
-rw-r--r-- | core/java/android/preference/PreferenceFragment.java | 309 |
1 files changed, 309 insertions, 0 deletions
diff --git a/core/java/android/preference/PreferenceFragment.java b/core/java/android/preference/PreferenceFragment.java new file mode 100644 index 0000000..f85bc9e --- /dev/null +++ b/core/java/android/preference/PreferenceFragment.java @@ -0,0 +1,309 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.preference; + +import android.app.Activity; +import android.app.Fragment; +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ListView; + +/** + * Shows a hierarchy of {@link Preference} objects as + * lists. These preferences will + * automatically save to {@link SharedPreferences} as the user interacts with + * them. To retrieve an instance of {@link SharedPreferences} that the + * preference hierarchy in this fragment will use, call + * {@link PreferenceManager#getDefaultSharedPreferences(android.content.Context)} + * with a context in the same package as this fragment. + * <p> + * The preference hierarchy can be formed in multiple ways: + * <li> From an XML file specifying the hierarchy + * <li> From different {@link Activity Activities} that each specify its own + * preferences in an XML file via {@link Activity} meta-data + * <li> From an object hierarchy rooted with {@link PreferenceScreen} + * <p> + * To inflate from XML, use the {@link #addPreferencesFromResource(int)}. The + * root element should be a {@link PreferenceScreen}. Subsequent elements can point + * to actual {@link Preference} subclasses. As mentioned above, subsequent + * {@link PreferenceScreen} in the hierarchy will result in the screen break. + * <p> + * To specify an {@link Intent} to query {@link Activity Activities} that each + * have preferences, use {@link #addPreferencesFromIntent}. Each + * {@link Activity} can specify meta-data in the manifest (via the key + * {@link PreferenceManager#METADATA_KEY_PREFERENCES}) that points to an XML + * resource. These XML resources will be inflated into a single preference + * hierarchy and shown by this fragment. + * <p> + * To specify an object hierarchy rooted with {@link PreferenceScreen}, use + * {@link #setPreferenceScreen(PreferenceScreen)}. + * <p> + * As a convenience, this fragment implements a click listener for any + * preference in the current hierarchy, see + * {@link #onPreferenceTreeClick(PreferenceScreen, Preference)}. + * <p> + * See {@link PreferenceActivity} for more details. + * + * <a name="SampleCode"></a> + * <h3>Sample Code</h3> + * + * <p>The following sample code shows the use if a PreferenceFragment to + * embed preferences in a larger activity and switch between them. The content + * layout of the activity is:</p> + * + * {@sample development/samples/ApiDemos/res/layout/fragment_preferences.xml layout} + * + * <p>The code using this layout consists of an activity and three fragments. + * One of the fragments is a list of categories the user can select; the other + * two are the different preference options for the categories.</p> + * + * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentPreferences.java + * activity} + * + * @see Preference + * @see PreferenceScreen + */ +public abstract class PreferenceFragment extends Fragment implements + PreferenceManager.OnPreferenceTreeClickListener { + + private static final String PREFERENCES_TAG = "android:preferences"; + + private PreferenceManager mPreferenceManager; + private ListView mList; + private boolean mHavePrefs; + private boolean mInitDone; + + /** + * The starting request code given out to preference framework. + */ + private static final int FIRST_REQUEST_CODE = 100; + + private static final int MSG_BIND_PREFERENCES = 0; + private Handler mHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + + case MSG_BIND_PREFERENCES: + bindPreferences(); + break; + } + } + }; + + final private Runnable mRequestFocus = new Runnable() { + public void run() { + mList.focusableViewAvailable(mList); + } + }; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mPreferenceManager = new PreferenceManager(getActivity(), FIRST_REQUEST_CODE); + mPreferenceManager.setOnPreferenceTreeClickListener(this); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + return inflater.inflate(com.android.internal.R.layout.preference_list_content, + container, false); + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + getListView().setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY); + + if (mHavePrefs) { + bindPreferences(); + } + + mInitDone = true; + + if (savedInstanceState != null) { + Bundle container = savedInstanceState.getBundle(PREFERENCES_TAG); + if (container != null) { + final PreferenceScreen preferenceScreen = getPreferenceScreen(); + if (preferenceScreen != null) { + preferenceScreen.restoreHierarchyState(container); + } + } + } + } + + @Override + public void onStop() { + super.onStop(); + mPreferenceManager.dispatchActivityStop(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + mPreferenceManager.dispatchActivityDestroy(); + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + + final PreferenceScreen preferenceScreen = getPreferenceScreen(); + if (preferenceScreen != null) { + Bundle container = new Bundle(); + preferenceScreen.saveHierarchyState(container); + outState.putBundle(PREFERENCES_TAG, container); + } + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + + mPreferenceManager.dispatchActivityResult(requestCode, resultCode, data); + } + + /** + * Returns the {@link PreferenceManager} used by this fragment. + * @return The {@link PreferenceManager}. + */ + public PreferenceManager getPreferenceManager() { + return mPreferenceManager; + } + + /** + * Sets the root of the preference hierarchy that this fragment is showing. + * + * @param preferenceScreen The root {@link PreferenceScreen} of the preference hierarchy. + */ + public void setPreferenceScreen(PreferenceScreen preferenceScreen) { + if (mPreferenceManager.setPreferences(preferenceScreen) && preferenceScreen != null) { + mHavePrefs = true; + if (mInitDone) { + postBindPreferences(); + } + } + } + + /** + * Gets the root of the preference hierarchy that this fragment is showing. + * + * @return The {@link PreferenceScreen} that is the root of the preference + * hierarchy. + */ + public PreferenceScreen getPreferenceScreen() { + return mPreferenceManager.getPreferenceScreen(); + } + + /** + * Adds preferences from activities that match the given {@link Intent}. + * + * @param intent The {@link Intent} to query activities. + */ + public void addPreferencesFromIntent(Intent intent) { + requirePreferenceManager(); + + setPreferenceScreen(mPreferenceManager.inflateFromIntent(intent, getPreferenceScreen())); + } + + /** + * Inflates the given XML resource and adds the preference hierarchy to the current + * preference hierarchy. + * + * @param preferencesResId The XML resource ID to inflate. + */ + public void addPreferencesFromResource(int preferencesResId) { + requirePreferenceManager(); + + setPreferenceScreen(mPreferenceManager.inflateFromResource(getActivity(), + preferencesResId, getPreferenceScreen())); + } + + /** + * {@inheritDoc} + */ + public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { + return false; + } + + /** + * Finds a {@link Preference} based on its key. + * + * @param key The key of the preference to retrieve. + * @return The {@link Preference} with the key, or null. + * @see PreferenceGroup#findPreference(CharSequence) + */ + public Preference findPreference(CharSequence key) { + if (mPreferenceManager == null) { + return null; + } + return mPreferenceManager.findPreference(key); + } + + private void requirePreferenceManager() { + if (mPreferenceManager == null) { + throw new RuntimeException("This should be called after super.onCreate."); + } + } + + private void postBindPreferences() { + if (mHandler.hasMessages(MSG_BIND_PREFERENCES)) return; + mHandler.obtainMessage(MSG_BIND_PREFERENCES).sendToTarget(); + } + + private void bindPreferences() { + final PreferenceScreen preferenceScreen = getPreferenceScreen(); + if (preferenceScreen != null) { + preferenceScreen.bind(getListView()); + } + } + + private ListView getListView() { + ensureList(); + return mList; + } + + private void ensureList() { + if (mList != null) { + return; + } + View root = getView(); + if (root == null) { + throw new IllegalStateException("Content view not yet created"); + } + View rawListView = root.findViewById(android.R.id.list); + if (!(rawListView instanceof ListView)) { + throw new RuntimeException( + "Content has view with id attribute 'android.R.id.list' " + + "that is not a ListView class"); + } + mList = (ListView)rawListView; + if (mList == null) { + throw new RuntimeException( + "Your content must have a ListView whose id attribute is " + + "'android.R.id.list'"); + } + mHandler.post(mRequestFocus); + } +} |