PreferenceFragment.java revision 014fea2a663ab0bc2d80a6293b84b2647a4a1895
142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn/*
242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * Copyright (C) 2010 The Android Open Source Project
342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn *
442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License");
542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * you may not use this file except in compliance with the License.
642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * You may obtain a copy of the License at
742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn *
842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn *      http://www.apache.org/licenses/LICENSE-2.0
942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn *
1042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * Unless required by applicable law or agreed to in writing, software
1142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS,
1242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * See the License for the specific language governing permissions and
1442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * limitations under the License.
1542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn */
1642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
1742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackbornpackage android.preference;
1842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
1942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackbornimport android.app.Activity;
2042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackbornimport android.app.Fragment;
2142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackbornimport android.content.Intent;
2242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackbornimport android.content.SharedPreferences;
2342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackbornimport android.os.Bundle;
2442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackbornimport android.os.Handler;
2542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackbornimport android.os.Message;
26014fea2a663ab0bc2d80a6293b84b2647a4a1895John Reckimport android.view.KeyEvent;
2742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackbornimport android.view.LayoutInflater;
2842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackbornimport android.view.View;
2942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackbornimport android.view.ViewGroup;
30014fea2a663ab0bc2d80a6293b84b2647a4a1895John Reckimport android.view.View.OnKeyListener;
3142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackbornimport android.widget.ListView;
3242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
3342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn/**
3442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * Shows a hierarchy of {@link Preference} objects as
3542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * lists. These preferences will
3642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * automatically save to {@link SharedPreferences} as the user interacts with
3742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * them. To retrieve an instance of {@link SharedPreferences} that the
3842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * preference hierarchy in this fragment will use, call
3942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * {@link PreferenceManager#getDefaultSharedPreferences(android.content.Context)}
4042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * with a context in the same package as this fragment.
4142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * <p>
42b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * Furthermore, the preferences shown will follow the visual style of system
43b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * preferences. It is easy to create a hierarchy of preferences (that can be
44b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * shown on multiple screens) via XML. For these reasons, it is recommended to
45b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * use this fragment (as a superclass) to deal with preferences in applications.
46b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * <p>
47b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * A {@link PreferenceScreen} object should be at the top of the preference
48b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * hierarchy. Furthermore, subsequent {@link PreferenceScreen} in the hierarchy
49b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * denote a screen break--that is the preferences contained within subsequent
50b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * {@link PreferenceScreen} should be shown on another screen. The preference
51b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * framework handles showing these other screens from the preference hierarchy.
52b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * <p>
5342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * The preference hierarchy can be formed in multiple ways:
5442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * <li> From an XML file specifying the hierarchy
5542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * <li> From different {@link Activity Activities} that each specify its own
5642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * preferences in an XML file via {@link Activity} meta-data
5742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * <li> From an object hierarchy rooted with {@link PreferenceScreen}
5842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * <p>
5942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * To inflate from XML, use the {@link #addPreferencesFromResource(int)}. The
6042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * root element should be a {@link PreferenceScreen}. Subsequent elements can point
6142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * to actual {@link Preference} subclasses. As mentioned above, subsequent
6242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * {@link PreferenceScreen} in the hierarchy will result in the screen break.
6342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * <p>
6442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * To specify an {@link Intent} to query {@link Activity Activities} that each
6542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * have preferences, use {@link #addPreferencesFromIntent}. Each
6642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * {@link Activity} can specify meta-data in the manifest (via the key
6742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * {@link PreferenceManager#METADATA_KEY_PREFERENCES}) that points to an XML
6842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * resource. These XML resources will be inflated into a single preference
6942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * hierarchy and shown by this fragment.
7042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * <p>
7142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * To specify an object hierarchy rooted with {@link PreferenceScreen}, use
7242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * {@link #setPreferenceScreen(PreferenceScreen)}.
7342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * <p>
7442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * As a convenience, this fragment implements a click listener for any
7542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * preference in the current hierarchy, see
7642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * {@link #onPreferenceTreeClick(PreferenceScreen, Preference)}.
7742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn *
7842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * <a name="SampleCode"></a>
7942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * <h3>Sample Code</h3>
8042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn *
81b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * <p>The following sample code shows a simple preference fragment that is
82b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * populated from a resource.  The resource it loads is:</p>
8342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn *
84b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * {@sample development/samples/ApiDemos/res/xml/preferences.xml preferences}
8542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn *
86b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * <p>The fragment implementation itself simply populates the preferences
87b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * when created.  Note that the preferences framework takes care of loading
88b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * the current values out of the app preferences and writing them when changed:</p>
8942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn *
90b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * {@sample development/samples/ApiDemos/src/com/example/android/apis/preference/FragmentPreferences.java
91b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn *      fragment}
9242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn *
9342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * @see Preference
9442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * @see PreferenceScreen
9542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn */
9642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackbornpublic abstract class PreferenceFragment extends Fragment implements
9742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        PreferenceManager.OnPreferenceTreeClickListener {
9842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
9942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    private static final String PREFERENCES_TAG = "android:preferences";
10042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
10142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    private PreferenceManager mPreferenceManager;
10242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    private ListView mList;
10342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    private boolean mHavePrefs;
10442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    private boolean mInitDone;
10542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
10642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    /**
10742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     * The starting request code given out to preference framework.
10842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     */
10942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    private static final int FIRST_REQUEST_CODE = 100;
11042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
1113e449ce00ed2d3b271e50bc7a52798f630973bf1Dianne Hackborn    private static final int MSG_BIND_PREFERENCES = 1;
11242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    private Handler mHandler = new Handler() {
11342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        @Override
11442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        public void handleMessage(Message msg) {
11542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn            switch (msg.what) {
11642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
11742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn                case MSG_BIND_PREFERENCES:
11842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn                    bindPreferences();
11942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn                    break;
12042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn            }
12142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        }
12242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    };
12342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
12442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    final private Runnable mRequestFocus = new Runnable() {
12542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        public void run() {
12642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn            mList.focusableViewAvailable(mList);
12742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        }
12842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    };
12942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
130b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn    /**
131b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn     * Interface that PreferenceFragment's containing activity should
132b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn     * implement to be able to process preference items that wish to
133b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn     * switch to a new fragment.
134b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn     */
135b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn    public interface OnPreferenceStartFragmentCallback {
136b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn        /**
137b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn         * Called when the user has clicked on a Preference that has
138b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn         * a fragment class name associated with it.  The implementation
139b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn         * to should instantiate and switch to an instance of the given
140b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn         * fragment.
141b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn         */
142b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn        boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref);
143b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn    }
144b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn
14542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    @Override
14642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    public void onCreate(Bundle savedInstanceState) {
14742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        super.onCreate(savedInstanceState);
14842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        mPreferenceManager = new PreferenceManager(getActivity(), FIRST_REQUEST_CODE);
14982e7bc11342547d1480ef89208ed06943650e201Amith Yamasani        mPreferenceManager.setFragment(this);
15042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    }
15142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
15242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    @Override
15342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    public View onCreateView(LayoutInflater inflater, ViewGroup container,
15442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn            Bundle savedInstanceState) {
155405c1af75607fafdb1d6faf34e13e032e4934787Amith Yamasani        return inflater.inflate(com.android.internal.R.layout.preference_list_fragment, container,
156405c1af75607fafdb1d6faf34e13e032e4934787Amith Yamasani                false);
15742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    }
15842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
15942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    @Override
16042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    public void onActivityCreated(Bundle savedInstanceState) {
16142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        super.onActivityCreated(savedInstanceState);
16242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        getListView().setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
16342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
16442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        if (mHavePrefs) {
16542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn            bindPreferences();
16642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        }
16742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
16842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        mInitDone = true;
16942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
17042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        if (savedInstanceState != null) {
17142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn            Bundle container = savedInstanceState.getBundle(PREFERENCES_TAG);
17242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn            if (container != null) {
17342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn                final PreferenceScreen preferenceScreen = getPreferenceScreen();
17442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn                if (preferenceScreen != null) {
17542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn                    preferenceScreen.restoreHierarchyState(container);
17642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn                }
17742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn            }
17842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        }
17942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    }
18042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
18142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    @Override
182c56fc753e2e2d35221a1a4df353a435098268ec4Amith Yamasani    public void onStart() {
183c56fc753e2e2d35221a1a4df353a435098268ec4Amith Yamasani        super.onStart();
184c56fc753e2e2d35221a1a4df353a435098268ec4Amith Yamasani        mPreferenceManager.setOnPreferenceTreeClickListener(this);
185c56fc753e2e2d35221a1a4df353a435098268ec4Amith Yamasani    }
186c56fc753e2e2d35221a1a4df353a435098268ec4Amith Yamasani
187c56fc753e2e2d35221a1a4df353a435098268ec4Amith Yamasani    @Override
18842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    public void onStop() {
18942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        super.onStop();
19042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        mPreferenceManager.dispatchActivityStop();
191c56fc753e2e2d35221a1a4df353a435098268ec4Amith Yamasani        mPreferenceManager.setOnPreferenceTreeClickListener(null);
19242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    }
19342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
19442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    @Override
195b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn    public void onDestroyView() {
196b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn        mList = null;
197b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn        mHandler.removeCallbacks(mRequestFocus);
19881d860013c7eeb96a09574301485d3e405ce03bcAmith Yamasani        mHandler.removeMessages(MSG_BIND_PREFERENCES);
199b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn        super.onDestroyView();
200b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn    }
201b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn
202b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn    @Override
20342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    public void onDestroy() {
20442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        super.onDestroy();
20542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        mPreferenceManager.dispatchActivityDestroy();
20642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    }
20742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
20842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    @Override
20942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    public void onSaveInstanceState(Bundle outState) {
21042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        super.onSaveInstanceState(outState);
21142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
21242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        final PreferenceScreen preferenceScreen = getPreferenceScreen();
21342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        if (preferenceScreen != null) {
21442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn            Bundle container = new Bundle();
21542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn            preferenceScreen.saveHierarchyState(container);
21642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn            outState.putBundle(PREFERENCES_TAG, container);
21742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        }
21842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    }
21942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
22042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    @Override
22142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    public void onActivityResult(int requestCode, int resultCode, Intent data) {
22242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        super.onActivityResult(requestCode, resultCode, data);
22342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
22442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        mPreferenceManager.dispatchActivityResult(requestCode, resultCode, data);
22542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    }
22642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
22742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    /**
22842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     * Returns the {@link PreferenceManager} used by this fragment.
22942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     * @return The {@link PreferenceManager}.
23042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     */
23142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    public PreferenceManager getPreferenceManager() {
23242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        return mPreferenceManager;
23342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    }
23442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
23542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    /**
23642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     * Sets the root of the preference hierarchy that this fragment is showing.
23742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     *
23842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     * @param preferenceScreen The root {@link PreferenceScreen} of the preference hierarchy.
23942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     */
24042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    public void setPreferenceScreen(PreferenceScreen preferenceScreen) {
24142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        if (mPreferenceManager.setPreferences(preferenceScreen) && preferenceScreen != null) {
24242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn            mHavePrefs = true;
24342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn            if (mInitDone) {
24442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn                postBindPreferences();
24542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn            }
24642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        }
24742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    }
24842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
24942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    /**
25042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     * Gets the root of the preference hierarchy that this fragment is showing.
25142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     *
25242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     * @return The {@link PreferenceScreen} that is the root of the preference
25342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     *         hierarchy.
25442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     */
25542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    public PreferenceScreen getPreferenceScreen() {
25642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        return mPreferenceManager.getPreferenceScreen();
25742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    }
25842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
25942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    /**
26042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     * Adds preferences from activities that match the given {@link Intent}.
26142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     *
26242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     * @param intent The {@link Intent} to query activities.
26342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     */
26442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    public void addPreferencesFromIntent(Intent intent) {
26542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        requirePreferenceManager();
26642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
26742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        setPreferenceScreen(mPreferenceManager.inflateFromIntent(intent, getPreferenceScreen()));
26842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    }
26942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
27042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    /**
27142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     * Inflates the given XML resource and adds the preference hierarchy to the current
27242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     * preference hierarchy.
27342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     *
27442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     * @param preferencesResId The XML resource ID to inflate.
27542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     */
27642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    public void addPreferencesFromResource(int preferencesResId) {
27742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        requirePreferenceManager();
27842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
27942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        setPreferenceScreen(mPreferenceManager.inflateFromResource(getActivity(),
28042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn                preferencesResId, getPreferenceScreen()));
28142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    }
28242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
28342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    /**
28442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     * {@inheritDoc}
28542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     */
286b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn    public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
287b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn            Preference preference) {
288b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn        if (preference.getFragment() != null &&
289b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn                getActivity() instanceof OnPreferenceStartFragmentCallback) {
290b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn            return ((OnPreferenceStartFragmentCallback)getActivity()).onPreferenceStartFragment(
291b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn                    this, preference);
292b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn        }
29342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        return false;
29442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    }
29542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
29642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    /**
29742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     * Finds a {@link Preference} based on its key.
29842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     *
29942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     * @param key The key of the preference to retrieve.
30042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     * @return The {@link Preference} with the key, or null.
30142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     * @see PreferenceGroup#findPreference(CharSequence)
30242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     */
30342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    public Preference findPreference(CharSequence key) {
30442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        if (mPreferenceManager == null) {
30542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn            return null;
30642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        }
30742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        return mPreferenceManager.findPreference(key);
30842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    }
30942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
31042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    private void requirePreferenceManager() {
31142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        if (mPreferenceManager == null) {
31242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn            throw new RuntimeException("This should be called after super.onCreate.");
31342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        }
31442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    }
31542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
31642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    private void postBindPreferences() {
31742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        if (mHandler.hasMessages(MSG_BIND_PREFERENCES)) return;
31842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        mHandler.obtainMessage(MSG_BIND_PREFERENCES).sendToTarget();
31942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    }
32042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
32142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    private void bindPreferences() {
32242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        final PreferenceScreen preferenceScreen = getPreferenceScreen();
32342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        if (preferenceScreen != null) {
32442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn            preferenceScreen.bind(getListView());
32542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        }
32642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    }
32742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
3289ae5473eae5312575521d87ec0303ac91560cbedAmith Yamasani    /** @hide */
3299ae5473eae5312575521d87ec0303ac91560cbedAmith Yamasani    public ListView getListView() {
33042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        ensureList();
33142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        return mList;
33242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    }
33342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
33442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    private void ensureList() {
33542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        if (mList != null) {
33642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn            return;
33742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        }
33842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        View root = getView();
33942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        if (root == null) {
34042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn            throw new IllegalStateException("Content view not yet created");
34142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        }
34242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        View rawListView = root.findViewById(android.R.id.list);
34342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        if (!(rawListView instanceof ListView)) {
34442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn            throw new RuntimeException(
34542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn                    "Content has view with id attribute 'android.R.id.list' "
34642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn                    + "that is not a ListView class");
34742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        }
34842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        mList = (ListView)rawListView;
34942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        if (mList == null) {
35042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn            throw new RuntimeException(
35142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn                    "Your content must have a ListView whose id attribute is " +
35242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn                    "'android.R.id.list'");
35342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        }
354014fea2a663ab0bc2d80a6293b84b2647a4a1895John Reck        mList.setOnKeyListener(mListOnKeyListener);
35542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        mHandler.post(mRequestFocus);
35642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    }
357014fea2a663ab0bc2d80a6293b84b2647a4a1895John Reck
358014fea2a663ab0bc2d80a6293b84b2647a4a1895John Reck    private OnKeyListener mListOnKeyListener = new OnKeyListener() {
359014fea2a663ab0bc2d80a6293b84b2647a4a1895John Reck
360014fea2a663ab0bc2d80a6293b84b2647a4a1895John Reck        @Override
361014fea2a663ab0bc2d80a6293b84b2647a4a1895John Reck        public boolean onKey(View v, int keyCode, KeyEvent event) {
362014fea2a663ab0bc2d80a6293b84b2647a4a1895John Reck            Object selectedItem = mList.getSelectedItem();
363014fea2a663ab0bc2d80a6293b84b2647a4a1895John Reck            if (selectedItem instanceof Preference) {
364014fea2a663ab0bc2d80a6293b84b2647a4a1895John Reck                View selectedView = mList.getSelectedView();
365014fea2a663ab0bc2d80a6293b84b2647a4a1895John Reck                return ((Preference)selectedItem).onKey(
366014fea2a663ab0bc2d80a6293b84b2647a4a1895John Reck                        selectedView, keyCode, event);
367014fea2a663ab0bc2d80a6293b84b2647a4a1895John Reck            }
368014fea2a663ab0bc2d80a6293b84b2647a4a1895John Reck            return false;
369014fea2a663ab0bc2d80a6293b84b2647a4a1895John Reck        }
370014fea2a663ab0bc2d80a6293b84b2647a4a1895John Reck
371014fea2a663ab0bc2d80a6293b84b2647a4a1895John Reck    };
37242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn}
373