16904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler/*
26904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * Copyright (C) 2015 The Android Open Source Project
36904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler *
46904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * Licensed under the Apache License, Version 2.0 (the "License");
56904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * you may not use this file except in compliance with the License.
66904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * You may obtain a copy of the License at
76904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler *
86904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler *      http://www.apache.org/licenses/LICENSE-2.0
96904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler *
106904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * Unless required by applicable law or agreed to in writing, software
116904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * distributed under the License is distributed on an "AS IS" BASIS,
126904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * See the License for the specific language governing permissions and
146904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * limitations under the License
156904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler */
166904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
176904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerpackage android.support.v14.preference;
186904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
196904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.app.DialogFragment;
206904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.app.Fragment;
216904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.content.Context;
226904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.content.res.TypedArray;
236904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.os.Bundle;
246904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.os.Handler;
256904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.os.Message;
266904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.support.annotation.Nullable;
276904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.support.annotation.XmlRes;
286904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.support.v7.preference.DialogPreference;
296904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.support.v7.preference.EditTextPreference;
306904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.support.v7.preference.ListPreference;
316904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.support.v7.preference.Preference;
3253b6dca0375b0b40d968f9e9d3dabda3e958fc41Tony Mantlerimport android.support.v7.preference.PreferenceGroupAdapter;
336904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.support.v7.preference.PreferenceManager;
346904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.support.v7.preference.PreferenceScreen;
356904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.support.v7.widget.LinearLayoutManager;
366904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.support.v7.widget.RecyclerView;
376904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.util.TypedValue;
386904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.view.ContextThemeWrapper;
396904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.view.LayoutInflater;
406904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.view.View;
416904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.view.ViewGroup;
426904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
436904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler/**
446904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * Shows a hierarchy of {@link Preference} objects as
456904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * lists. These preferences will
466904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * automatically save to {@link android.content.SharedPreferences} as the user interacts with
476904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * them. To retrieve an instance of {@link android.content.SharedPreferences} that the
486904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * preference hierarchy in this fragment will use, call
496904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * {@link PreferenceManager#getDefaultSharedPreferences(android.content.Context)}
506904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * with a context in the same package as this fragment.
516904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * <p>
526904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * Furthermore, the preferences shown will follow the visual style of system
536904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * preferences. It is easy to create a hierarchy of preferences (that can be
546904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * shown on multiple screens) via XML. For these reasons, it is recommended to
556904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * use this fragment (as a superclass) to deal with preferences in applications.
566904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * <p>
576904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * A {@link PreferenceScreen} object should be at the top of the preference
586904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * hierarchy. Furthermore, subsequent {@link PreferenceScreen} in the hierarchy
596904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * denote a screen break--that is the preferences contained within subsequent
606904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * {@link PreferenceScreen} should be shown on another screen. The preference
616904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * framework handles showing these other screens from the preference hierarchy.
626904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * <p>
636904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * The preference hierarchy can be formed in multiple ways:
646904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * <li> From an XML file specifying the hierarchy
656904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * <li> From different {@link android.app.Activity Activities} that each specify its own
666904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * preferences in an XML file via {@link android.app.Activity} meta-data
676904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * <li> From an object hierarchy rooted with {@link PreferenceScreen}
686904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * <p>
696904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * To inflate from XML, use the {@link #addPreferencesFromResource(int)}. The
706904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * root element should be a {@link PreferenceScreen}. Subsequent elements can point
716904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * to actual {@link Preference} subclasses. As mentioned above, subsequent
726904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * {@link PreferenceScreen} in the hierarchy will result in the screen break.
736904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * <p>
746904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * To specify an object hierarchy rooted with {@link PreferenceScreen}, use
756904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * {@link #setPreferenceScreen(PreferenceScreen)}.
766904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * <p>
776904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * As a convenience, this fragment implements a click listener for any
786904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * preference in the current hierarchy, see
796904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * {@link #onPreferenceTreeClick(Preference)}.
806904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler *
816904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * <div class="special reference">
826904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * <h3>Developer Guides</h3>
836904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * <p>For information about using {@code PreferenceFragment},
846904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * read the <a href="{@docRoot}guide/topics/ui/settings.html">Settings</a>
856904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * guide.</p>
866904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * </div>
876904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler *
886904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * <a name="SampleCode"></a>
896904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * <h3>Sample Code</h3>
906904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler *
916904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * <p>The following sample code shows a simple preference fragment that is
926904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * populated from a resource.  The resource it loads is:</p>
936904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler *
946904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * {@sample development/samples/ApiDemos/res/xml/preferences.xml preferences}
956904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler *
966904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * <p>The fragment implementation itself simply populates the preferences
976904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * when created.  Note that the preferences framework takes care of loading
986904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * the current values out of the app preferences and writing them when changed:</p>
996904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler *
1006904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * {@sample development/samples/ApiDemos/src/com/example/android/apis/preference/FragmentPreferences.java
1016904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler *      fragment}
1026904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler *
1036904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * @see Preference
1046904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * @see PreferenceScreen
1056904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler */
1066904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerpublic abstract class PreferenceFragment extends Fragment implements
1076904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        PreferenceManager.OnPreferenceTreeClickListener,
1086904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        PreferenceManager.OnDisplayPreferenceDialogListener,
1096904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        PreferenceManager.OnNavigateToScreenListener,
1106904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        DialogPreference.TargetFragment {
1116904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
1126904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    /**
1136904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * Fragment argument used to specify the tag of the desired root
1146904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * {@link android.support.v7.preference.PreferenceScreen} object.
1156904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     */
1166904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    public static final String ARG_PREFERENCE_ROOT =
1176904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            "android.support.v7.preference.PreferenceFragmentCompat.PREFERENCE_ROOT";
1186904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
1196904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    private static final String PREFERENCES_TAG = "android:preferences";
1206904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
1216904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    private static final String DIALOG_FRAGMENT_TAG =
1226904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            "android.support.v14.preference.PreferenceFragment.DIALOG";
1236904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
1246904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    private PreferenceManager mPreferenceManager;
1256904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    private RecyclerView mList;
1266904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    private boolean mHavePrefs;
1276904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    private boolean mInitDone;
1286904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
1296904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    private Context mStyledContext;
1306904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
1316904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    private int mLayoutResId = R.layout.preference_list_fragment;
1326904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
1336904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    /**
1346904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * The starting request code given out to preference framework.
1356904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     */
1366904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    private static final int FIRST_REQUEST_CODE = 100;
1376904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
1386904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    private static final int MSG_BIND_PREFERENCES = 1;
1396904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    private Handler mHandler = new Handler() {
1406904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        @Override
1416904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        public void handleMessage(Message msg) {
1426904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            switch (msg.what) {
1436904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
1446904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler                case MSG_BIND_PREFERENCES:
1456904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler                    bindPreferences();
1466904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler                    break;
1476904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            }
1486904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        }
1496904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    };
1506904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
1516904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    final private Runnable mRequestFocus = new Runnable() {
1526904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        public void run() {
1536904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            mList.focusableViewAvailable(mList);
1546904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        }
1556904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    };
1566904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
1576904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    /**
1586904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * Interface that PreferenceFragment's containing activity should
1596904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * implement to be able to process preference items that wish to
1606904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * switch to a specified fragment.
1616904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     */
1626904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    public interface OnPreferenceStartFragmentCallback {
1636904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        /**
1646904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler         * Called when the user has clicked on a Preference that has
1656904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler         * a fragment class name associated with it.  The implementation
16653b6dca0375b0b40d968f9e9d3dabda3e958fc41Tony Mantler         * should instantiate and switch to an instance of the given
1676904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler         * fragment.
168bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler         * @param caller The fragment requesting navigation.
169bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler         * @param pref The preference requesting the fragment.
170bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler         * @return true if the fragment creation has been handled
1716904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler         */
1726904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref);
1736904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
1746904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
1756904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    /**
1766904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * Interface that PreferenceFragment's containing activity should
1776904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * implement to be able to process preference items that wish to
1786904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * switch to a new screen of preferences.
1796904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     */
1806904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    public interface OnPreferenceStartScreenCallback {
1816904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        /**
1826904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler         * Called when the user has clicked on a PreferenceScreen item in order to navigate to a new
1836904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler         * screen of preferences.
1846904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler         * @param caller The fragment requesting navigation.
1856904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler         * @param pref The preference screen to navigate to.
186bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler         * @return true if the screen navigation has been handled
1876904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler         */
1886904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        boolean onPreferenceStartScreen(PreferenceFragment caller, PreferenceScreen pref);
1896904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
1906904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
191bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler    public interface OnPreferenceDisplayDialogCallback {
192bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler
193bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler        /**
194bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler         *
195bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler         * @param caller The fragment containing the preference requesting the dialog.
196bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler         * @param pref The preference requesting the dialog.
197bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler         * @return true if the dialog creation has been handled.
198bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler         */
199bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler        boolean onPreferenceDisplayDialog(PreferenceFragment caller, Preference pref);
200bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler    }
201bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler
2026904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    @Override
2036904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    public void onCreate(Bundle savedInstanceState) {
2046904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        super.onCreate(savedInstanceState);
2056904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        final TypedValue tv = new TypedValue();
2066904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        getActivity().getTheme().resolveAttribute(R.attr.preferenceTheme, tv, true);
2076904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        final int theme = tv.resourceId;
2086904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        if (theme <= 0) {
2096904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            throw new IllegalStateException("Must specify preferenceTheme in theme");
2106904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        }
2116904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        mStyledContext = new ContextThemeWrapper(getActivity(), theme);
2126904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
2136904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        mPreferenceManager = new PreferenceManager(mStyledContext);
2146904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        mPreferenceManager.setOnNavigateToScreenListener(this);
2156904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        final Bundle args = getArguments();
2166904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        final String rootKey;
2176904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        if (args != null) {
2186904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            rootKey = getArguments().getString(ARG_PREFERENCE_ROOT);
2196904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        } else {
2206904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            rootKey = null;
2216904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        }
2226904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        onCreatePreferences(savedInstanceState, rootKey);
2236904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
2246904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
2256904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    /**
2266904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * Called during {@link #onCreate(Bundle)} to supply the preferences for this fragment.
2276904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * Subclasses are expected to call {@link #setPreferenceScreen(PreferenceScreen)} either
2286904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * directly or via helper methods such as {@link #addPreferencesFromResource(int)}.
2296904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     *
2306904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * @param savedInstanceState If the fragment is being re-created from
2316904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     *                           a previous saved state, this is the state.
2326904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * @param rootKey If non-null, this preference fragment should be rooted at the
2336904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     *                {@link android.support.v7.preference.PreferenceScreen} with this key.
2346904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     */
2356904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    public abstract void onCreatePreferences(Bundle savedInstanceState, String rootKey);
2366904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
2376904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    @Override
2386904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    public View onCreateView(LayoutInflater inflater, ViewGroup container,
2396904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            Bundle savedInstanceState) {
2406904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
2416904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        TypedArray a = mStyledContext.obtainStyledAttributes(null,
2426904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler                R.styleable.PreferenceFragmentCompat,
2436904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler                R.attr.preferenceFragmentStyle,
2446904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler                0);
2456904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
2466904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        mLayoutResId = a.getResourceId(R.styleable.PreferenceFragmentCompat_layout,
2476904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler                mLayoutResId);
2486904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
2496904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        a.recycle();
2506904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
2516904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        final View view = inflater.inflate(mLayoutResId, container, false);
2526904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
2536904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        final View rawListContainer = view.findViewById(R.id.list_container);
2546904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        if (!(rawListContainer instanceof ViewGroup)) {
2556904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            throw new RuntimeException("Content has view with id attribute 'R.id.list_container' "
2566904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler                    + "that is not a ViewGroup class");
2576904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        }
2586904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
2596904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        final ViewGroup listContainer = (ViewGroup) rawListContainer;
2606904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
2616904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        final RecyclerView listView = onCreateRecyclerView(inflater, listContainer,
2626904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler                savedInstanceState);
2636904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        if (listView == null) {
2646904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            throw new RuntimeException("Could not create RecyclerView");
2656904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        }
2666904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
2676904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        mList = listView;
2686904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        listContainer.addView(mList);
2696904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        mHandler.post(mRequestFocus);
2706904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        return view;
2716904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
2726904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
2736904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    @Override
2746904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    public void onActivityCreated(Bundle savedInstanceState) {
2756904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        super.onActivityCreated(savedInstanceState);
2766904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
2776904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        if (mHavePrefs) {
2786904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            bindPreferences();
2796904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        }
2806904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
2816904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        mInitDone = true;
2826904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
2836904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        if (savedInstanceState != null) {
2846904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            Bundle container = savedInstanceState.getBundle(PREFERENCES_TAG);
2856904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            if (container != null) {
2866904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler                final PreferenceScreen preferenceScreen = getPreferenceScreen();
2876904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler                if (preferenceScreen != null) {
2886904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler                    preferenceScreen.restoreHierarchyState(container);
2896904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler                }
2906904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            }
2916904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        }
2926904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
2936904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
2946904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    @Override
2956904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    public void onStart() {
2966904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        super.onStart();
2976904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        mPreferenceManager.setOnPreferenceTreeClickListener(this);
2986904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        mPreferenceManager.setOnDisplayPreferenceDialogListener(this);
2996904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
3006904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
3016904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    @Override
3026904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    public void onStop() {
3036904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        super.onStop();
3046904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        mPreferenceManager.setOnPreferenceTreeClickListener(null);
3056904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        mPreferenceManager.setOnDisplayPreferenceDialogListener(null);
3066904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
3076904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
3086904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    @Override
3096904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    public void onDestroyView() {
3106904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        mList = null;
3116904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        mHandler.removeCallbacks(mRequestFocus);
3126904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        mHandler.removeMessages(MSG_BIND_PREFERENCES);
3136904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        super.onDestroyView();
3146904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
3156904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
3166904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    @Override
3176904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    public void onSaveInstanceState(Bundle outState) {
3186904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        super.onSaveInstanceState(outState);
3196904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
3206904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        final PreferenceScreen preferenceScreen = getPreferenceScreen();
3216904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        if (preferenceScreen != null) {
3226904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            Bundle container = new Bundle();
3236904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            preferenceScreen.saveHierarchyState(container);
3246904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            outState.putBundle(PREFERENCES_TAG, container);
3256904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        }
3266904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
3276904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
3286904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    /**
3296904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * Returns the {@link PreferenceManager} used by this fragment.
3306904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * @return The {@link PreferenceManager}.
3316904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     */
3326904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    public PreferenceManager getPreferenceManager() {
3336904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        return mPreferenceManager;
3346904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
3356904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
3366904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    /**
3376904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * Sets the root of the preference hierarchy that this fragment is showing.
3386904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     *
3396904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * @param preferenceScreen The root {@link PreferenceScreen} of the preference hierarchy.
3406904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     */
3416904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    public void setPreferenceScreen(PreferenceScreen preferenceScreen) {
3426904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        if (mPreferenceManager.setPreferences(preferenceScreen) && preferenceScreen != null) {
3436904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            onUnbindPreferences();
3446904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            mHavePrefs = true;
3456904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            if (mInitDone) {
3466904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler                postBindPreferences();
3476904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            }
3486904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        }
3496904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
3506904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
3516904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    /**
3526904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * Gets the root of the preference hierarchy that this fragment is showing.
3536904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     *
3546904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * @return The {@link PreferenceScreen} that is the root of the preference
3556904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     *         hierarchy.
3566904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     */
3576904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    public PreferenceScreen getPreferenceScreen() {
3586904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        return mPreferenceManager.getPreferenceScreen();
3596904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
3606904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
3616904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    /**
3626904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * Inflates the given XML resource and adds the preference hierarchy to the current
3636904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * preference hierarchy.
3646904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     *
3656904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * @param preferencesResId The XML resource ID to inflate.
3666904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     */
3676904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    public void addPreferencesFromResource(@XmlRes int preferencesResId) {
3686904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        requirePreferenceManager();
3696904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
3706904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        setPreferenceScreen(mPreferenceManager.inflateFromResource(mStyledContext,
3716904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler                preferencesResId, getPreferenceScreen()));
3726904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
3736904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
3746904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    /**
3756904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * Inflates the given XML resource and replaces the current preference hierarchy (if any) with
3766904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * the preference hierarchy rooted at {@code key}.
3776904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     *
3786904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * @param preferencesResId The XML resource ID to inflate.
3796904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * @param key The preference key of the {@link android.support.v7.preference.PreferenceScreen}
3806904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     *            to use as the root of the preference hierarchy, or null to use the root
3816904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     *            {@link android.support.v7.preference.PreferenceScreen}.
3826904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     */
3836904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    public void setPreferencesFromResource(@XmlRes int preferencesResId, @Nullable String key) {
3846904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        requirePreferenceManager();
3856904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
3866904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        final PreferenceScreen xmlRoot = mPreferenceManager.inflateFromResource(mStyledContext,
3876904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler                preferencesResId, null);
3886904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
3896904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        final Preference root;
3906904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        if (key != null) {
3916904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            root = xmlRoot.findPreference(key);
3926904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            if (!(root instanceof PreferenceScreen)) {
3936904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler                throw new IllegalArgumentException("Preference object with key " + key
3946904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler                        + " is not a PreferenceScreen");
3956904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            }
3966904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        } else {
3976904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            root = xmlRoot;
3986904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        }
3996904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
4006904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        setPreferenceScreen((PreferenceScreen) root);
4016904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
4026904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
4036904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    /**
4046904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * {@inheritDoc}
4056904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     */
4066904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    public boolean onPreferenceTreeClick(Preference preference) {
407c4868c8a2946a038466f51875a590759092137b2Tony Mantler        if (preference.getFragment() != null) {
408c4868c8a2946a038466f51875a590759092137b2Tony Mantler            boolean handled = false;
40941e6b178ef361cdadcf27b8074e71b624df8fe3fTony Mantler            if (getCallbackFragment() instanceof OnPreferenceStartFragmentCallback) {
41041e6b178ef361cdadcf27b8074e71b624df8fe3fTony Mantler                handled = ((OnPreferenceStartFragmentCallback) getCallbackFragment())
411c4868c8a2946a038466f51875a590759092137b2Tony Mantler                        .onPreferenceStartFragment(this, preference);
412c4868c8a2946a038466f51875a590759092137b2Tony Mantler            }
413c4868c8a2946a038466f51875a590759092137b2Tony Mantler            if (!handled && getActivity() instanceof OnPreferenceStartFragmentCallback){
414c4868c8a2946a038466f51875a590759092137b2Tony Mantler                handled = ((OnPreferenceStartFragmentCallback) getActivity())
415c4868c8a2946a038466f51875a590759092137b2Tony Mantler                        .onPreferenceStartFragment(this, preference);
416c4868c8a2946a038466f51875a590759092137b2Tony Mantler            }
417c4868c8a2946a038466f51875a590759092137b2Tony Mantler            return handled;
4186904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        }
4196904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        return false;
4206904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
4216904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
4226904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    /**
4236904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * Called by
4246904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * {@link android.support.v7.preference.PreferenceScreen#onClick()} in order to navigate to a
4256904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * new screen of preferences. Calls
4266904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * {@link PreferenceFragment.OnPreferenceStartScreenCallback#onPreferenceStartScreen}
427c4868c8a2946a038466f51875a590759092137b2Tony Mantler     * if the target fragment or containing activity implements
4286904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * {@link PreferenceFragment.OnPreferenceStartScreenCallback}.
4296904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * @param preferenceScreen The {@link android.support.v7.preference.PreferenceScreen} to
4306904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     *                         navigate to.
4316904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     */
4326904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    @Override
4336904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    public void onNavigateToScreen(PreferenceScreen preferenceScreen) {
434bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler        boolean handled = false;
43541e6b178ef361cdadcf27b8074e71b624df8fe3fTony Mantler        if (getCallbackFragment() instanceof OnPreferenceStartScreenCallback) {
43641e6b178ef361cdadcf27b8074e71b624df8fe3fTony Mantler            handled = ((OnPreferenceStartScreenCallback) getCallbackFragment())
437bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler                    .onPreferenceStartScreen(this, preferenceScreen);
438bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler        }
439bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler        if (!handled && getActivity() instanceof OnPreferenceStartScreenCallback) {
440bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler            ((OnPreferenceStartScreenCallback) getActivity())
441bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler                    .onPreferenceStartScreen(this, preferenceScreen);
4426904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        }
4436904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
4446904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
4456904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    /**
4466904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * Finds a {@link Preference} based on its key.
4476904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     *
4486904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * @param key The key of the preference to retrieve.
4496904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * @return The {@link Preference} with the key, or null.
4506904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * @see android.support.v7.preference.PreferenceGroup#findPreference(CharSequence)
4516904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     */
4526904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    public Preference findPreference(CharSequence key) {
4536904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        if (mPreferenceManager == null) {
4546904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            return null;
4556904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        }
4566904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        return mPreferenceManager.findPreference(key);
4576904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
4586904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
4596904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    private void requirePreferenceManager() {
4606904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        if (mPreferenceManager == null) {
4616904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            throw new RuntimeException("This should be called after super.onCreate.");
4626904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        }
4636904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
4646904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
4656904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    private void postBindPreferences() {
4666904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        if (mHandler.hasMessages(MSG_BIND_PREFERENCES)) return;
4676904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        mHandler.obtainMessage(MSG_BIND_PREFERENCES).sendToTarget();
4686904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
4696904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
4706904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    private void bindPreferences() {
4716904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        final PreferenceScreen preferenceScreen = getPreferenceScreen();
4726904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        if (preferenceScreen != null) {
47353b6dca0375b0b40d968f9e9d3dabda3e958fc41Tony Mantler            getListView().setAdapter(onCreateAdapter(preferenceScreen));
474e61b4475e1837034d8926593aff9d35f8dfaebe2Tony Mantler            preferenceScreen.onAttached();
4756904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        }
4766904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        onBindPreferences();
4776904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
4786904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
4796904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    /** @hide */
4806904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    protected void onBindPreferences() {
4816904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
4826904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
4836904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    /** @hide */
4846904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    protected void onUnbindPreferences() {
4856904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
4866904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
4876904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    public final RecyclerView getListView() {
4886904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        return mList;
4896904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
4906904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
4916904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    /**
4926904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * Creates the {@link android.support.v7.widget.RecyclerView} used to display the preferences.
4936904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * Subclasses may override this to return a customized
4946904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * {@link android.support.v7.widget.RecyclerView}.
4956904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * @param inflater The LayoutInflater object that can be used to inflate the
4966904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     *                 {@link android.support.v7.widget.RecyclerView}.
4976904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * @param parent The parent {@link android.view.View} that the RecyclerView will be attached to.
4986904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     *               This method should not add the view itself, but this can be used to generate
4996904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     *               the LayoutParams of the view.
5006904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * @param savedInstanceState If non-null, this view is being re-constructed from a previous
5016904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     *                           saved state as given here
5026904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * @return A new RecyclerView object to be placed into the view hierarchy
5036904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     */
5046904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    public RecyclerView onCreateRecyclerView(LayoutInflater inflater, ViewGroup parent,
5056904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            Bundle savedInstanceState) {
5066904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        RecyclerView recyclerView = (RecyclerView) inflater
5076904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler                .inflate(R.layout.preference_recyclerview, parent, false);
5086904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
5096904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        recyclerView.setLayoutManager(onCreateLayoutManager());
5106904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
5116904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        return recyclerView;
5126904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
5136904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
5146904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    /**
5156904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * Called from {@link #onCreateRecyclerView} to create the
5166904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * {@link android.support.v7.widget.RecyclerView.LayoutManager} for the created
5176904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * {@link android.support.v7.widget.RecyclerView}.
5186904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * @return A new {@link android.support.v7.widget.RecyclerView.LayoutManager} instance.
5196904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     */
5206904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    public RecyclerView.LayoutManager onCreateLayoutManager() {
5216904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        return new LinearLayoutManager(getActivity());
5226904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
5236904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
5246904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    /**
52553b6dca0375b0b40d968f9e9d3dabda3e958fc41Tony Mantler     * Creates the root adapter.
52653b6dca0375b0b40d968f9e9d3dabda3e958fc41Tony Mantler     *
52753b6dca0375b0b40d968f9e9d3dabda3e958fc41Tony Mantler     * @param preferenceScreen Preference screen object to create the adapter for.
52853b6dca0375b0b40d968f9e9d3dabda3e958fc41Tony Mantler     * @return An adapter that contains the preferences contained in this {@link PreferenceScreen}.
52953b6dca0375b0b40d968f9e9d3dabda3e958fc41Tony Mantler     */
53053b6dca0375b0b40d968f9e9d3dabda3e958fc41Tony Mantler    protected RecyclerView.Adapter onCreateAdapter(PreferenceScreen preferenceScreen) {
53153b6dca0375b0b40d968f9e9d3dabda3e958fc41Tony Mantler        return new PreferenceGroupAdapter(preferenceScreen);
53253b6dca0375b0b40d968f9e9d3dabda3e958fc41Tony Mantler    }
53353b6dca0375b0b40d968f9e9d3dabda3e958fc41Tony Mantler
53453b6dca0375b0b40d968f9e9d3dabda3e958fc41Tony Mantler    /**
5356904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * Called when a preference in the tree requests to display a dialog. Subclasses should
5366904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * override this method to display custom dialogs or to handle dialogs for custom preference
5376904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * classes.
5386904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     *
5396904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * @param preference The Preference object requesting the dialog.
5406904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     */
5416904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    @Override
5426904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    public void onDisplayPreferenceDialog(Preference preference) {
543bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler
544bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler        boolean handled = false;
54541e6b178ef361cdadcf27b8074e71b624df8fe3fTony Mantler        if (getCallbackFragment() instanceof OnPreferenceDisplayDialogCallback) {
54641e6b178ef361cdadcf27b8074e71b624df8fe3fTony Mantler            handled = ((OnPreferenceDisplayDialogCallback) getCallbackFragment())
547bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler                    .onPreferenceDisplayDialog(this, preference);
548bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler        }
549bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler        if (!handled && getActivity() instanceof OnPreferenceDisplayDialogCallback) {
550bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler            handled = ((OnPreferenceDisplayDialogCallback) getActivity())
551bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler                    .onPreferenceDisplayDialog(this, preference);
552bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler        }
553bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler
554bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler        if (handled) {
555bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler            return;
556bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler        }
557bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler
5586904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        // check if dialog is already showing
5596904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        if (getFragmentManager().findFragmentByTag(DIALOG_FRAGMENT_TAG) != null) {
5606904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            return;
5616904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        }
5626904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
5636904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        final DialogFragment f;
5646904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        if (preference instanceof EditTextPreference) {
5656904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            f = EditTextPreferenceDialogFragment.newInstance(preference.getKey());
5666904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        } else if (preference instanceof ListPreference) {
5676904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            f = ListPreferenceDialogFragment.newInstance(preference.getKey());
5680112bacf4aa212f4d0da45594a88694f295ae56cTony Mantler        } else if (preference instanceof MultiSelectListPreference) {
5690112bacf4aa212f4d0da45594a88694f295ae56cTony Mantler            f = MultiSelectListPreferenceDialogFragment.newInstance(preference.getKey());
5706904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        } else {
5716904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            throw new IllegalArgumentException("Tried to display dialog for unknown " +
5726904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler                    "preference type. Did you forget to override onDisplayPreferenceDialog()?");
5736904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        }
5746904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        f.setTargetFragment(this, 0);
5756904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        f.show(getFragmentManager(), DIALOG_FRAGMENT_TAG);
5766904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
5776904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
57841e6b178ef361cdadcf27b8074e71b624df8fe3fTony Mantler    /**
57941e6b178ef361cdadcf27b8074e71b624df8fe3fTony Mantler     * Basically a wrapper for getParentFragment which is v17+. Used by the leanback preference lib.
58041e6b178ef361cdadcf27b8074e71b624df8fe3fTony Mantler     * @return Fragment to possibly use as a callback
58141e6b178ef361cdadcf27b8074e71b624df8fe3fTony Mantler     * @hide
58241e6b178ef361cdadcf27b8074e71b624df8fe3fTony Mantler     */
58341e6b178ef361cdadcf27b8074e71b624df8fe3fTony Mantler    public Fragment getCallbackFragment() {
58441e6b178ef361cdadcf27b8074e71b624df8fe3fTony Mantler        return null;
58541e6b178ef361cdadcf27b8074e71b624df8fe3fTony Mantler    }
5866904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler}
587