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)}.
77cdd0c59a0108036895796dcb2bea69ff5eef26caScott Main *
78cdd0c59a0108036895796dcb2bea69ff5eef26caScott Main * <div class="special reference">
79cdd0c59a0108036895796dcb2bea69ff5eef26caScott Main * <h3>Developer Guides</h3>
80cdd0c59a0108036895796dcb2bea69ff5eef26caScott Main * <p>For information about using {@code PreferenceFragment},
81cdd0c59a0108036895796dcb2bea69ff5eef26caScott Main * read the <a href="{@docRoot}guide/topics/ui/settings.html">Settings</a>
82cdd0c59a0108036895796dcb2bea69ff5eef26caScott Main * guide.</p>
83cdd0c59a0108036895796dcb2bea69ff5eef26caScott Main * </div>
8442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn *
8542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * <a name="SampleCode"></a>
8642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * <h3>Sample Code</h3>
8742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn *
88b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * <p>The following sample code shows a simple preference fragment that is
89b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * populated from a resource.  The resource it loads is:</p>
9042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn *
91b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * {@sample development/samples/ApiDemos/res/xml/preferences.xml preferences}
9242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn *
93b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * <p>The fragment implementation itself simply populates the preferences
94b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * when created.  Note that the preferences framework takes care of loading
95b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * the current values out of the app preferences and writing them when changed:</p>
9642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn *
97b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * {@sample development/samples/ApiDemos/src/com/example/android/apis/preference/FragmentPreferences.java
98b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn *      fragment}
9942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn *
10042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * @see Preference
10142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn * @see PreferenceScreen
10242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn */
10342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackbornpublic abstract class PreferenceFragment extends Fragment implements
10442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        PreferenceManager.OnPreferenceTreeClickListener {
10542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
10642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    private static final String PREFERENCES_TAG = "android:preferences";
10742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
10842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    private PreferenceManager mPreferenceManager;
10942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    private ListView mList;
11042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    private boolean mHavePrefs;
11142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    private boolean mInitDone;
11242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
11342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    /**
11442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     * The starting request code given out to preference framework.
11542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     */
11642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    private static final int FIRST_REQUEST_CODE = 100;
11742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
1183e449ce00ed2d3b271e50bc7a52798f630973bf1Dianne Hackborn    private static final int MSG_BIND_PREFERENCES = 1;
11942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    private Handler mHandler = new Handler() {
12042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        @Override
12142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        public void handleMessage(Message msg) {
12242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn            switch (msg.what) {
12342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
12442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn                case MSG_BIND_PREFERENCES:
12542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn                    bindPreferences();
12642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn                    break;
12742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn            }
12842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        }
12942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    };
13042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
13142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    final private Runnable mRequestFocus = new Runnable() {
13242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        public void run() {
13342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn            mList.focusableViewAvailable(mList);
13442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        }
13542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    };
13642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
137b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn    /**
138b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn     * Interface that PreferenceFragment's containing activity should
139b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn     * implement to be able to process preference items that wish to
140b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn     * switch to a new fragment.
141b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn     */
142b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn    public interface OnPreferenceStartFragmentCallback {
143b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn        /**
144b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn         * Called when the user has clicked on a Preference that has
145b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn         * a fragment class name associated with it.  The implementation
146b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn         * to should instantiate and switch to an instance of the given
147b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn         * fragment.
148b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn         */
149b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn        boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref);
150b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn    }
151b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn
15242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    @Override
15342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    public void onCreate(Bundle savedInstanceState) {
15442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        super.onCreate(savedInstanceState);
15542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        mPreferenceManager = new PreferenceManager(getActivity(), FIRST_REQUEST_CODE);
15682e7bc11342547d1480ef89208ed06943650e201Amith Yamasani        mPreferenceManager.setFragment(this);
15742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    }
15842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
15942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    @Override
16042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    public View onCreateView(LayoutInflater inflater, ViewGroup container,
16142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn            Bundle savedInstanceState) {
162405c1af75607fafdb1d6faf34e13e032e4934787Amith Yamasani        return inflater.inflate(com.android.internal.R.layout.preference_list_fragment, container,
163405c1af75607fafdb1d6faf34e13e032e4934787Amith Yamasani                false);
16442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    }
16542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
16642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    @Override
16742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    public void onActivityCreated(Bundle savedInstanceState) {
16842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        super.onActivityCreated(savedInstanceState);
16942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
17042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        if (mHavePrefs) {
17142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn            bindPreferences();
17242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        }
17342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
17442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        mInitDone = true;
17542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
17642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        if (savedInstanceState != null) {
17742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn            Bundle container = savedInstanceState.getBundle(PREFERENCES_TAG);
17842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn            if (container != null) {
17942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn                final PreferenceScreen preferenceScreen = getPreferenceScreen();
18042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn                if (preferenceScreen != null) {
18142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn                    preferenceScreen.restoreHierarchyState(container);
18242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn                }
18342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn            }
18442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        }
18542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    }
18642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
18742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    @Override
188c56fc753e2e2d35221a1a4df353a435098268ec4Amith Yamasani    public void onStart() {
189c56fc753e2e2d35221a1a4df353a435098268ec4Amith Yamasani        super.onStart();
190c56fc753e2e2d35221a1a4df353a435098268ec4Amith Yamasani        mPreferenceManager.setOnPreferenceTreeClickListener(this);
191c56fc753e2e2d35221a1a4df353a435098268ec4Amith Yamasani    }
192c56fc753e2e2d35221a1a4df353a435098268ec4Amith Yamasani
193c56fc753e2e2d35221a1a4df353a435098268ec4Amith Yamasani    @Override
19442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    public void onStop() {
19542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        super.onStop();
19642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        mPreferenceManager.dispatchActivityStop();
197c56fc753e2e2d35221a1a4df353a435098268ec4Amith Yamasani        mPreferenceManager.setOnPreferenceTreeClickListener(null);
19842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    }
19942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
20042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    @Override
201b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn    public void onDestroyView() {
202b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn        mList = null;
203b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn        mHandler.removeCallbacks(mRequestFocus);
20481d860013c7eeb96a09574301485d3e405ce03bcAmith Yamasani        mHandler.removeMessages(MSG_BIND_PREFERENCES);
205b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn        super.onDestroyView();
206b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn    }
207b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn
208b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn    @Override
20942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    public void onDestroy() {
21042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        super.onDestroy();
21142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        mPreferenceManager.dispatchActivityDestroy();
21242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    }
21342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
21442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    @Override
21542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    public void onSaveInstanceState(Bundle outState) {
21642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        super.onSaveInstanceState(outState);
21742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
21842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        final PreferenceScreen preferenceScreen = getPreferenceScreen();
21942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        if (preferenceScreen != null) {
22042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn            Bundle container = new Bundle();
22142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn            preferenceScreen.saveHierarchyState(container);
22242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn            outState.putBundle(PREFERENCES_TAG, container);
22342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        }
22442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    }
22542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
22642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    @Override
22742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    public void onActivityResult(int requestCode, int resultCode, Intent data) {
22842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        super.onActivityResult(requestCode, resultCode, data);
22942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
23042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        mPreferenceManager.dispatchActivityResult(requestCode, resultCode, data);
23142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    }
23242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
23342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    /**
23442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     * Returns the {@link PreferenceManager} used by this fragment.
23542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     * @return The {@link PreferenceManager}.
23642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     */
23742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    public PreferenceManager getPreferenceManager() {
23842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        return mPreferenceManager;
23942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    }
24042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
24142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    /**
24242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     * Sets the root of the preference hierarchy that this fragment is showing.
24342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     *
24442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     * @param preferenceScreen The root {@link PreferenceScreen} of the preference hierarchy.
24542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     */
24642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    public void setPreferenceScreen(PreferenceScreen preferenceScreen) {
24742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        if (mPreferenceManager.setPreferences(preferenceScreen) && preferenceScreen != null) {
24842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn            mHavePrefs = true;
24942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn            if (mInitDone) {
25042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn                postBindPreferences();
25142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn            }
25242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        }
25342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    }
25442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
25542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    /**
25642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     * Gets the root of the preference hierarchy that this fragment is showing.
25742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     *
25842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     * @return The {@link PreferenceScreen} that is the root of the preference
25942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     *         hierarchy.
26042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     */
26142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    public PreferenceScreen getPreferenceScreen() {
26242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        return mPreferenceManager.getPreferenceScreen();
26342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    }
26442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
26542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    /**
26642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     * Adds preferences from activities that match the given {@link Intent}.
26742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     *
26842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     * @param intent The {@link Intent} to query activities.
26942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     */
27042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    public void addPreferencesFromIntent(Intent intent) {
27142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        requirePreferenceManager();
27242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
27342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        setPreferenceScreen(mPreferenceManager.inflateFromIntent(intent, getPreferenceScreen()));
27442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    }
27542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
27642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    /**
27742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     * Inflates the given XML resource and adds the preference hierarchy to the current
27842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     * preference hierarchy.
27942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     *
28042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     * @param preferencesResId The XML resource ID to inflate.
28142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     */
28242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    public void addPreferencesFromResource(int preferencesResId) {
28342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        requirePreferenceManager();
28442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
28542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        setPreferenceScreen(mPreferenceManager.inflateFromResource(getActivity(),
28642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn                preferencesResId, getPreferenceScreen()));
28742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    }
28842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
28942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    /**
29042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     * {@inheritDoc}
29142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     */
292b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn    public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
293b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn            Preference preference) {
294b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn        if (preference.getFragment() != null &&
295b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn                getActivity() instanceof OnPreferenceStartFragmentCallback) {
296b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn            return ((OnPreferenceStartFragmentCallback)getActivity()).onPreferenceStartFragment(
297b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn                    this, preference);
298b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn        }
29942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        return false;
30042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    }
30142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
30242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    /**
30342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     * Finds a {@link Preference} based on its key.
30442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     *
30542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     * @param key The key of the preference to retrieve.
30642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     * @return The {@link Preference} with the key, or null.
30742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     * @see PreferenceGroup#findPreference(CharSequence)
30842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn     */
30942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    public Preference findPreference(CharSequence key) {
31042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        if (mPreferenceManager == null) {
31142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn            return null;
31242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        }
31342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        return mPreferenceManager.findPreference(key);
31442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    }
31542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
31642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    private void requirePreferenceManager() {
31742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        if (mPreferenceManager == null) {
31842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn            throw new RuntimeException("This should be called after super.onCreate.");
31942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        }
32042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    }
32142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
32242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    private void postBindPreferences() {
32342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        if (mHandler.hasMessages(MSG_BIND_PREFERENCES)) return;
32442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        mHandler.obtainMessage(MSG_BIND_PREFERENCES).sendToTarget();
32542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    }
32642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
32742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    private void bindPreferences() {
32842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        final PreferenceScreen preferenceScreen = getPreferenceScreen();
32942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        if (preferenceScreen != null) {
33042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn            preferenceScreen.bind(getListView());
33142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        }
33242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    }
33342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
3349ae5473eae5312575521d87ec0303ac91560cbedAmith Yamasani    /** @hide */
3359ae5473eae5312575521d87ec0303ac91560cbedAmith Yamasani    public ListView getListView() {
33642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        ensureList();
33742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        return mList;
33842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    }
33942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn
34042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    private void ensureList() {
34142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        if (mList != null) {
34242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn            return;
34342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        }
34442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        View root = getView();
34542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        if (root == null) {
34642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn            throw new IllegalStateException("Content view not yet created");
34742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        }
34842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        View rawListView = root.findViewById(android.R.id.list);
34942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        if (!(rawListView instanceof ListView)) {
35042c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn            throw new RuntimeException(
35142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn                    "Content has view with id attribute 'android.R.id.list' "
35242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn                    + "that is not a ListView class");
35342c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        }
35442c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        mList = (ListView)rawListView;
35542c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        if (mList == null) {
35642c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn            throw new RuntimeException(
35742c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn                    "Your content must have a ListView whose id attribute is " +
35842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn                    "'android.R.id.list'");
35942c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        }
360014fea2a663ab0bc2d80a6293b84b2647a4a1895John Reck        mList.setOnKeyListener(mListOnKeyListener);
36142c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn        mHandler.post(mRequestFocus);
36242c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn    }
363014fea2a663ab0bc2d80a6293b84b2647a4a1895John Reck
364014fea2a663ab0bc2d80a6293b84b2647a4a1895John Reck    private OnKeyListener mListOnKeyListener = new OnKeyListener() {
365014fea2a663ab0bc2d80a6293b84b2647a4a1895John Reck
366014fea2a663ab0bc2d80a6293b84b2647a4a1895John Reck        @Override
367014fea2a663ab0bc2d80a6293b84b2647a4a1895John Reck        public boolean onKey(View v, int keyCode, KeyEvent event) {
368014fea2a663ab0bc2d80a6293b84b2647a4a1895John Reck            Object selectedItem = mList.getSelectedItem();
369014fea2a663ab0bc2d80a6293b84b2647a4a1895John Reck            if (selectedItem instanceof Preference) {
370014fea2a663ab0bc2d80a6293b84b2647a4a1895John Reck                View selectedView = mList.getSelectedView();
371014fea2a663ab0bc2d80a6293b84b2647a4a1895John Reck                return ((Preference)selectedItem).onKey(
372014fea2a663ab0bc2d80a6293b84b2647a4a1895John Reck                        selectedView, keyCode, event);
373014fea2a663ab0bc2d80a6293b84b2647a4a1895John Reck            }
374014fea2a663ab0bc2d80a6293b84b2647a4a1895John Reck            return false;
375014fea2a663ab0bc2d80a6293b84b2647a4a1895John Reck        }
376014fea2a663ab0bc2d80a6293b84b2647a4a1895John Reck
377014fea2a663ab0bc2d80a6293b84b2647a4a1895John Reck    };
37842c2936f3c6e048caafb17eb9fe91fa4a33c8b86Dianne Hackborn}
379