[go: nahoru, domu]

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;
231fcd004668b5a9038c312e4426031027d8641353Tony Mantlerimport android.graphics.Canvas;
241fcd004668b5a9038c312e4426031027d8641353Tony Mantlerimport android.graphics.Rect;
251fcd004668b5a9038c312e4426031027d8641353Tony Mantlerimport android.graphics.drawable.Drawable;
266904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.os.Bundle;
276904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.os.Handler;
286904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.os.Message;
296904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.support.annotation.Nullable;
306904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.support.annotation.XmlRes;
313fadd62b614e4a69aefe920aac640bdb629e502eJason Monkimport android.support.v4.content.res.TypedArrayUtils;
321fcd004668b5a9038c312e4426031027d8641353Tony Mantlerimport android.support.v4.view.ViewCompat;
333fadd62b614e4a69aefe920aac640bdb629e502eJason Monkimport android.support.v7.preference.AndroidResources;
346904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.support.v7.preference.DialogPreference;
356904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.support.v7.preference.EditTextPreference;
366904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.support.v7.preference.ListPreference;
376904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.support.v7.preference.Preference;
3866222008cbda61251014caf1442930a48561d25cTony Mantlerimport android.support.v7.preference.PreferenceGroup;
3953b6dca0375b0b40d968f9e9d3dabda3e958fc41Tony Mantlerimport android.support.v7.preference.PreferenceGroupAdapter;
406904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.support.v7.preference.PreferenceManager;
411553af7799b550e0821a5e579db0bccf1f0835b8Steven Daoimport android.support.v7.preference.PreferenceRecyclerViewAccessibilityDelegate;
426904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.support.v7.preference.PreferenceScreen;
431fcd004668b5a9038c312e4426031027d8641353Tony Mantlerimport android.support.v7.preference.PreferenceViewHolder;
446904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.support.v7.widget.LinearLayoutManager;
456904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.support.v7.widget.RecyclerView;
466904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.util.TypedValue;
476904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.view.ContextThemeWrapper;
486904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.view.LayoutInflater;
496904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.view.View;
506904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.view.ViewGroup;
516904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
526904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler/**
536904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * Shows a hierarchy of {@link Preference} objects as
546904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * lists. These preferences will
556904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * automatically save to {@link android.content.SharedPreferences} as the user interacts with
566904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * them. To retrieve an instance of {@link android.content.SharedPreferences} that the
576904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * preference hierarchy in this fragment will use, call
586904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * {@link PreferenceManager#getDefaultSharedPreferences(android.content.Context)}
596904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * with a context in the same package as this fragment.
606904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * <p>
616904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * Furthermore, the preferences shown will follow the visual style of system
626904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * preferences. It is easy to create a hierarchy of preferences (that can be
636904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * shown on multiple screens) via XML. For these reasons, it is recommended to
646904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * use this fragment (as a superclass) to deal with preferences in applications.
656904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * <p>
666904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * A {@link PreferenceScreen} object should be at the top of the preference
676904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * hierarchy. Furthermore, subsequent {@link PreferenceScreen} in the hierarchy
686904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * denote a screen break--that is the preferences contained within subsequent
696904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * {@link PreferenceScreen} should be shown on another screen. The preference
70ee1e0dfa158dab873977c50c746749f55a4c1251Tony Mantler * framework handles this by calling {@link #onNavigateToScreen(PreferenceScreen)}.
716904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * <p>
726904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * The preference hierarchy can be formed in multiple ways:
736904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * <li> From an XML file specifying the hierarchy
746904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * <li> From different {@link android.app.Activity Activities} that each specify its own
756904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * preferences in an XML file via {@link android.app.Activity} meta-data
766904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * <li> From an object hierarchy rooted with {@link PreferenceScreen}
776904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * <p>
786904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * To inflate from XML, use the {@link #addPreferencesFromResource(int)}. The
796904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * root element should be a {@link PreferenceScreen}. Subsequent elements can point
806904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * to actual {@link Preference} subclasses. As mentioned above, subsequent
816904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * {@link PreferenceScreen} in the hierarchy will result in the screen break.
826904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * <p>
836904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * To specify an object hierarchy rooted with {@link PreferenceScreen}, use
846904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * {@link #setPreferenceScreen(PreferenceScreen)}.
856904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * <p>
866904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * As a convenience, this fragment implements a click listener for any
876904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * preference in the current hierarchy, see
886904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * {@link #onPreferenceTreeClick(Preference)}.
896904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler *
906904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * <div class="special reference">
916904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * <h3>Developer Guides</h3>
926904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * <p>For information about using {@code PreferenceFragment},
936904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * read the <a href="{@docRoot}guide/topics/ui/settings.html">Settings</a>
946904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * guide.</p>
956904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * </div>
966904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler *
976904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * <a name="SampleCode"></a>
986904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * <h3>Sample Code</h3>
996904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler *
1006904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * <p>The following sample code shows a simple preference fragment that is
1016904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * populated from a resource.  The resource it loads is:</p>
1026904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler *
1036904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * {@sample development/samples/ApiDemos/res/xml/preferences.xml preferences}
1046904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler *
1056904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * <p>The fragment implementation itself simply populates the preferences
1066904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * when created.  Note that the preferences framework takes care of loading
1076904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * the current values out of the app preferences and writing them when changed:</p>
1086904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler *
1096904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * {@sample development/samples/ApiDemos/src/com/example/android/apis/preference/FragmentPreferences.java
1106904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler *      fragment}
1116904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler *
1126904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * @see Preference
1136904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * @see PreferenceScreen
1146904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler */
1156904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerpublic abstract class PreferenceFragment extends Fragment implements
1166904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        PreferenceManager.OnPreferenceTreeClickListener,
1176904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        PreferenceManager.OnDisplayPreferenceDialogListener,
1186904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        PreferenceManager.OnNavigateToScreenListener,
1196904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        DialogPreference.TargetFragment {
1206904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
1216904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    /**
1226904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * Fragment argument used to specify the tag of the desired root
1236904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * {@link android.support.v7.preference.PreferenceScreen} object.
1246904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     */
1256904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    public static final String ARG_PREFERENCE_ROOT =
1266904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            "android.support.v7.preference.PreferenceFragmentCompat.PREFERENCE_ROOT";
1276904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
1286904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    private static final String PREFERENCES_TAG = "android:preferences";
1296904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
1306904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    private static final String DIALOG_FRAGMENT_TAG =
1316904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            "android.support.v14.preference.PreferenceFragment.DIALOG";
1326904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
1336904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    private PreferenceManager mPreferenceManager;
1346904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    private RecyclerView mList;
1356904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    private boolean mHavePrefs;
1366904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    private boolean mInitDone;
1376904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
1386904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    private Context mStyledContext;
1396904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
1406759b1021d8198ad1d239bb30e5a102b99624bceAdam Lesinski    private int mLayoutResId = android.support.v7.preference.R.layout.preference_list_fragment;
1416904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
1421fcd004668b5a9038c312e4426031027d8641353Tony Mantler    private final DividerDecoration mDividerDecoration = new DividerDecoration();
1431fcd004668b5a9038c312e4426031027d8641353Tony Mantler
1446904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    private static final int MSG_BIND_PREFERENCES = 1;
1456904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    private Handler mHandler = new Handler() {
1466904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        @Override
1476904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        public void handleMessage(Message msg) {
1486904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            switch (msg.what) {
1496904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
1506904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler                case MSG_BIND_PREFERENCES:
1516904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler                    bindPreferences();
1526904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler                    break;
1536904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            }
1546904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        }
1556904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    };
1566904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
1576904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    final private Runnable mRequestFocus = new Runnable() {
1586904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        public void run() {
1596904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            mList.focusableViewAvailable(mList);
1606904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        }
1616904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    };
1626904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
16366222008cbda61251014caf1442930a48561d25cTony Mantler    private Runnable mSelectPreferenceRunnable;
16466222008cbda61251014caf1442930a48561d25cTony Mantler
1656904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    /**
1666904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * Interface that PreferenceFragment's containing activity should
1676904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * implement to be able to process preference items that wish to
1686904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * switch to a specified fragment.
1696904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     */
1706904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    public interface OnPreferenceStartFragmentCallback {
1716904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        /**
1726904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler         * Called when the user has clicked on a Preference that has
1736904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler         * a fragment class name associated with it.  The implementation
17453b6dca0375b0b40d968f9e9d3dabda3e958fc41Tony Mantler         * should instantiate and switch to an instance of the given
1756904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler         * fragment.
176bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler         * @param caller The fragment requesting navigation.
177bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler         * @param pref The preference requesting the fragment.
178bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler         * @return true if the fragment creation has been handled
1796904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler         */
1806904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref);
1816904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
1826904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
1836904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    /**
1846904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * Interface that PreferenceFragment's containing activity should
1856904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * implement to be able to process preference items that wish to
1866904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * switch to a new screen of preferences.
1876904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     */
1886904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    public interface OnPreferenceStartScreenCallback {
1896904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        /**
1906904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler         * Called when the user has clicked on a PreferenceScreen item in order to navigate to a new
1916904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler         * screen of preferences.
1926904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler         * @param caller The fragment requesting navigation.
1936904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler         * @param pref The preference screen to navigate to.
194bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler         * @return true if the screen navigation has been handled
1956904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler         */
1966904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        boolean onPreferenceStartScreen(PreferenceFragment caller, PreferenceScreen pref);
1976904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
1986904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
199bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler    public interface OnPreferenceDisplayDialogCallback {
200bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler
201bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler        /**
202bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler         *
203bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler         * @param caller The fragment containing the preference requesting the dialog.
204bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler         * @param pref The preference requesting the dialog.
205bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler         * @return true if the dialog creation has been handled.
206bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler         */
207bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler        boolean onPreferenceDisplayDialog(PreferenceFragment caller, Preference pref);
208bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler    }
209bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler
2106904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    @Override
2116904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    public void onCreate(Bundle savedInstanceState) {
2126904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        super.onCreate(savedInstanceState);
2136904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        final TypedValue tv = new TypedValue();
2146759b1021d8198ad1d239bb30e5a102b99624bceAdam Lesinski        getActivity().getTheme().resolveAttribute(
2156759b1021d8198ad1d239bb30e5a102b99624bceAdam Lesinski                android.support.v7.preference.R.attr.preferenceTheme, tv, true);
2166904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        final int theme = tv.resourceId;
2176904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        if (theme <= 0) {
2186904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            throw new IllegalStateException("Must specify preferenceTheme in theme");
2196904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        }
2206904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        mStyledContext = new ContextThemeWrapper(getActivity(), theme);
2216904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
2226904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        mPreferenceManager = new PreferenceManager(mStyledContext);
2236904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        mPreferenceManager.setOnNavigateToScreenListener(this);
2246904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        final Bundle args = getArguments();
2256904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        final String rootKey;
2266904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        if (args != null) {
2276904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            rootKey = getArguments().getString(ARG_PREFERENCE_ROOT);
2286904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        } else {
2296904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            rootKey = null;
2306904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        }
2316904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        onCreatePreferences(savedInstanceState, rootKey);
2326904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
2336904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
2346904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    /**
2356904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * Called during {@link #onCreate(Bundle)} to supply the preferences for this fragment.
2366904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * Subclasses are expected to call {@link #setPreferenceScreen(PreferenceScreen)} either
2376904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * directly or via helper methods such as {@link #addPreferencesFromResource(int)}.
2386904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     *
2396904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * @param savedInstanceState If the fragment is being re-created from
2406904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     *                           a previous saved state, this is the state.
2416904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * @param rootKey If non-null, this preference fragment should be rooted at the
2426904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     *                {@link android.support.v7.preference.PreferenceScreen} with this key.
2436904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     */
2446904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    public abstract void onCreatePreferences(Bundle savedInstanceState, String rootKey);
2456904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
2466904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    @Override
2476904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    public View onCreateView(LayoutInflater inflater, ViewGroup container,
2486904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            Bundle savedInstanceState) {
2496904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
2506904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        TypedArray a = mStyledContext.obtainStyledAttributes(null,
2511fcd004668b5a9038c312e4426031027d8641353Tony Mantler                R.styleable.PreferenceFragment,
2526759b1021d8198ad1d239bb30e5a102b99624bceAdam Lesinski                TypedArrayUtils.getAttr(mStyledContext,
2536759b1021d8198ad1d239bb30e5a102b99624bceAdam Lesinski                        android.support.v7.preference.R.attr.preferenceFragmentStyle,
2543fadd62b614e4a69aefe920aac640bdb629e502eJason Monk                        AndroidResources.ANDROID_R_PREFERENCE_FRAGMENT_STYLE),
2556904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler                0);
2566904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
2571fcd004668b5a9038c312e4426031027d8641353Tony Mantler        mLayoutResId = a.getResourceId(R.styleable.PreferenceFragment_android_layout, mLayoutResId);
2581fcd004668b5a9038c312e4426031027d8641353Tony Mantler
2591fcd004668b5a9038c312e4426031027d8641353Tony Mantler        final Drawable divider = a.getDrawable(R.styleable.PreferenceFragment_android_divider);
260301061d5655864f03f9bab0a28f7c3f2e28a0a04Tony Mantler        final int dividerHeight = a.getDimensionPixelSize(
261301061d5655864f03f9bab0a28f7c3f2e28a0a04Tony Mantler                R.styleable.PreferenceFragment_android_dividerHeight, -1);
2626904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
2636904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        a.recycle();
2646904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
2651273d7f81a35bc244a8221a518a30e5443d24e08Tony Mantler        // Need to theme the inflater to pick up the preferenceFragmentListStyle
2661273d7f81a35bc244a8221a518a30e5443d24e08Tony Mantler        final TypedValue tv = new TypedValue();
2676759b1021d8198ad1d239bb30e5a102b99624bceAdam Lesinski        getActivity().getTheme().resolveAttribute(
2686759b1021d8198ad1d239bb30e5a102b99624bceAdam Lesinski                android.support.v7.preference.R.attr.preferenceTheme, tv, true);
2691273d7f81a35bc244a8221a518a30e5443d24e08Tony Mantler        final int theme = tv.resourceId;
2701273d7f81a35bc244a8221a518a30e5443d24e08Tony Mantler
2711273d7f81a35bc244a8221a518a30e5443d24e08Tony Mantler        final Context themedContext = new ContextThemeWrapper(inflater.getContext(), theme);
2721273d7f81a35bc244a8221a518a30e5443d24e08Tony Mantler        final LayoutInflater themedInflater = inflater.cloneInContext(themedContext);
2731273d7f81a35bc244a8221a518a30e5443d24e08Tony Mantler
2741273d7f81a35bc244a8221a518a30e5443d24e08Tony Mantler        final View view = themedInflater.inflate(mLayoutResId, container, false);
2756904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
2763fadd62b614e4a69aefe920aac640bdb629e502eJason Monk        final View rawListContainer = view.findViewById(AndroidResources.ANDROID_R_LIST_CONTAINER);
2776904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        if (!(rawListContainer instanceof ViewGroup)) {
2783fadd62b614e4a69aefe920aac640bdb629e502eJason Monk            throw new RuntimeException("Content has view with id attribute "
2793fadd62b614e4a69aefe920aac640bdb629e502eJason Monk                    + "'android.R.id.list_container' that is not a ViewGroup class");
2806904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        }
2816904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
2826904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        final ViewGroup listContainer = (ViewGroup) rawListContainer;
2836904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
2841273d7f81a35bc244a8221a518a30e5443d24e08Tony Mantler        final RecyclerView listView = onCreateRecyclerView(themedInflater, listContainer,
2856904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler                savedInstanceState);
2866904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        if (listView == null) {
2876904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            throw new RuntimeException("Could not create RecyclerView");
2886904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        }
2896904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
2906904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        mList = listView;
2911fcd004668b5a9038c312e4426031027d8641353Tony Mantler
2921fcd004668b5a9038c312e4426031027d8641353Tony Mantler        listView.addItemDecoration(mDividerDecoration);
2931fcd004668b5a9038c312e4426031027d8641353Tony Mantler        setDivider(divider);
2941fcd004668b5a9038c312e4426031027d8641353Tony Mantler        if (dividerHeight != -1) {
2951fcd004668b5a9038c312e4426031027d8641353Tony Mantler            setDividerHeight(dividerHeight);
2961fcd004668b5a9038c312e4426031027d8641353Tony Mantler        }
2971fcd004668b5a9038c312e4426031027d8641353Tony Mantler
2986904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        listContainer.addView(mList);
2996904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        mHandler.post(mRequestFocus);
30066222008cbda61251014caf1442930a48561d25cTony Mantler
3016904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        return view;
3026904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
3036904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
3041fcd004668b5a9038c312e4426031027d8641353Tony Mantler    /**
3051fcd004668b5a9038c312e4426031027d8641353Tony Mantler     * Sets the drawable that will be drawn between each item in the list.
3061fcd004668b5a9038c312e4426031027d8641353Tony Mantler     * <p>
3071fcd004668b5a9038c312e4426031027d8641353Tony Mantler     * <strong>Note:</strong> If the drawable does not have an intrinsic
3081fcd004668b5a9038c312e4426031027d8641353Tony Mantler     * height, you should also call {@link #setDividerHeight(int)}.
3091fcd004668b5a9038c312e4426031027d8641353Tony Mantler     *
3101fcd004668b5a9038c312e4426031027d8641353Tony Mantler     * @param divider the drawable to use
3111fcd004668b5a9038c312e4426031027d8641353Tony Mantler     * @attr ref R.styleable#PreferenceFragment_android_divider
3121fcd004668b5a9038c312e4426031027d8641353Tony Mantler     */
3131fcd004668b5a9038c312e4426031027d8641353Tony Mantler    public void setDivider(Drawable divider) {
3141fcd004668b5a9038c312e4426031027d8641353Tony Mantler        mDividerDecoration.setDivider(divider);
3151fcd004668b5a9038c312e4426031027d8641353Tony Mantler    }
3161fcd004668b5a9038c312e4426031027d8641353Tony Mantler
3171fcd004668b5a9038c312e4426031027d8641353Tony Mantler    /**
3181fcd004668b5a9038c312e4426031027d8641353Tony Mantler     * Sets the height of the divider that will be drawn between each item in the list. Calling
3191fcd004668b5a9038c312e4426031027d8641353Tony Mantler     * this will override the intrinsic height as set by {@link #setDivider(Drawable)}
3201fcd004668b5a9038c312e4426031027d8641353Tony Mantler     *
3211fcd004668b5a9038c312e4426031027d8641353Tony Mantler     * @param height The new height of the divider in pixels.
3221fcd004668b5a9038c312e4426031027d8641353Tony Mantler     * @attr ref R.styleable#PreferenceFragment_android_dividerHeight
3231fcd004668b5a9038c312e4426031027d8641353Tony Mantler     */
3241fcd004668b5a9038c312e4426031027d8641353Tony Mantler    public void setDividerHeight(int height) {
3251fcd004668b5a9038c312e4426031027d8641353Tony Mantler        mDividerDecoration.setDividerHeight(height);
3261fcd004668b5a9038c312e4426031027d8641353Tony Mantler    }
3271fcd004668b5a9038c312e4426031027d8641353Tony Mantler
3286904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    @Override
3298f7f0d48fac8f83e90a04ba67f9a03f93c6ed262Jason Monk    public void onViewCreated(View view, Bundle savedInstanceState) {
3308f7f0d48fac8f83e90a04ba67f9a03f93c6ed262Jason Monk        super.onViewCreated(view, savedInstanceState);
3316904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
3326904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        if (mHavePrefs) {
3336904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            bindPreferences();
33466222008cbda61251014caf1442930a48561d25cTony Mantler            if (mSelectPreferenceRunnable != null) {
33566222008cbda61251014caf1442930a48561d25cTony Mantler                mSelectPreferenceRunnable.run();
33666222008cbda61251014caf1442930a48561d25cTony Mantler                mSelectPreferenceRunnable = null;
33766222008cbda61251014caf1442930a48561d25cTony Mantler            }
3386904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        }
3396904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
3406904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        mInitDone = true;
3418f7f0d48fac8f83e90a04ba67f9a03f93c6ed262Jason Monk    }
3428f7f0d48fac8f83e90a04ba67f9a03f93c6ed262Jason Monk
3438f7f0d48fac8f83e90a04ba67f9a03f93c6ed262Jason Monk    @Override
3448f7f0d48fac8f83e90a04ba67f9a03f93c6ed262Jason Monk    public void onActivityCreated(Bundle savedInstanceState) {
3458f7f0d48fac8f83e90a04ba67f9a03f93c6ed262Jason Monk        super.onActivityCreated(savedInstanceState);
3466904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
3476904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        if (savedInstanceState != null) {
3486904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            Bundle container = savedInstanceState.getBundle(PREFERENCES_TAG);
3496904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            if (container != null) {
3506904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler                final PreferenceScreen preferenceScreen = getPreferenceScreen();
3516904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler                if (preferenceScreen != null) {
3526904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler                    preferenceScreen.restoreHierarchyState(container);
3536904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler                }
3546904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            }
3556904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        }
3566904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
3576904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
3586904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    @Override
3596904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    public void onStart() {
3606904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        super.onStart();
3616904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        mPreferenceManager.setOnPreferenceTreeClickListener(this);
3626904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        mPreferenceManager.setOnDisplayPreferenceDialogListener(this);
3636904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
3646904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
3656904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    @Override
3666904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    public void onStop() {
3676904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        super.onStop();
3686904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        mPreferenceManager.setOnPreferenceTreeClickListener(null);
3696904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        mPreferenceManager.setOnDisplayPreferenceDialogListener(null);
3706904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
3716904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
3726904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    @Override
3736904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    public void onDestroyView() {
3746904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        mHandler.removeCallbacks(mRequestFocus);
3756904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        mHandler.removeMessages(MSG_BIND_PREFERENCES);
3768f7f0d48fac8f83e90a04ba67f9a03f93c6ed262Jason Monk        if (mHavePrefs) {
3778f7f0d48fac8f83e90a04ba67f9a03f93c6ed262Jason Monk            unbindPreferences();
3788f7f0d48fac8f83e90a04ba67f9a03f93c6ed262Jason Monk        }
3798f7f0d48fac8f83e90a04ba67f9a03f93c6ed262Jason Monk        mList = null;
3806904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        super.onDestroyView();
3816904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
3826904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
3836904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    @Override
3846904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    public void onSaveInstanceState(Bundle outState) {
3856904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        super.onSaveInstanceState(outState);
3866904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
3876904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        final PreferenceScreen preferenceScreen = getPreferenceScreen();
3886904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        if (preferenceScreen != null) {
3896904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            Bundle container = new Bundle();
3906904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            preferenceScreen.saveHierarchyState(container);
3916904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            outState.putBundle(PREFERENCES_TAG, container);
3926904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        }
3936904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
3946904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
3956904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    /**
3966904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * Returns the {@link PreferenceManager} used by this fragment.
3976904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * @return The {@link PreferenceManager}.
3986904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     */
3996904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    public PreferenceManager getPreferenceManager() {
4006904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        return mPreferenceManager;
4016904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
4026904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
4036904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    /**
4046904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * Sets the root of the preference hierarchy that this fragment is showing.
4056904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     *
4066904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * @param preferenceScreen The root {@link PreferenceScreen} of the preference hierarchy.
4076904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     */
4086904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    public void setPreferenceScreen(PreferenceScreen preferenceScreen) {
4096904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        if (mPreferenceManager.setPreferences(preferenceScreen) && preferenceScreen != null) {
4106904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            onUnbindPreferences();
4116904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            mHavePrefs = true;
4126904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            if (mInitDone) {
4136904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler                postBindPreferences();
4146904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            }
4156904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        }
4166904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
4176904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
4186904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    /**
4196904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * Gets the root of the preference hierarchy that this fragment is showing.
4206904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     *
4216904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * @return The {@link PreferenceScreen} that is the root of the preference
4226904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     *         hierarchy.
4236904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     */
4246904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    public PreferenceScreen getPreferenceScreen() {
4256904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        return mPreferenceManager.getPreferenceScreen();
4266904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
4276904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
4286904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    /**
4296904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * Inflates the given XML resource and adds the preference hierarchy to the current
4306904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * preference hierarchy.
4316904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     *
4326904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * @param preferencesResId The XML resource ID to inflate.
4336904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     */
4346904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    public void addPreferencesFromResource(@XmlRes int preferencesResId) {
4356904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        requirePreferenceManager();
4366904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
4376904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        setPreferenceScreen(mPreferenceManager.inflateFromResource(mStyledContext,
4386904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler                preferencesResId, getPreferenceScreen()));
4396904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
4406904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
4416904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    /**
4426904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * Inflates the given XML resource and replaces the current preference hierarchy (if any) with
4436904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * the preference hierarchy rooted at {@code key}.
4446904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     *
4456904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * @param preferencesResId The XML resource ID to inflate.
4466904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * @param key The preference key of the {@link android.support.v7.preference.PreferenceScreen}
4476904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     *            to use as the root of the preference hierarchy, or null to use the root
4486904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     *            {@link android.support.v7.preference.PreferenceScreen}.
4496904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     */
4506904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    public void setPreferencesFromResource(@XmlRes int preferencesResId, @Nullable String key) {
4516904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        requirePreferenceManager();
4526904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
4536904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        final PreferenceScreen xmlRoot = mPreferenceManager.inflateFromResource(mStyledContext,
4546904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler                preferencesResId, null);
4556904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
4566904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        final Preference root;
4576904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        if (key != null) {
4586904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            root = xmlRoot.findPreference(key);
4596904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            if (!(root instanceof PreferenceScreen)) {
4606904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler                throw new IllegalArgumentException("Preference object with key " + key
4616904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler                        + " is not a PreferenceScreen");
4626904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            }
4636904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        } else {
4646904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            root = xmlRoot;
4656904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        }
4666904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
4676904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        setPreferenceScreen((PreferenceScreen) root);
4686904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
4696904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
4706904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    /**
4716904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * {@inheritDoc}
4726904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     */
4736904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    public boolean onPreferenceTreeClick(Preference preference) {
474c4868c8a2946a038466f51875a590759092137b2Tony Mantler        if (preference.getFragment() != null) {
475c4868c8a2946a038466f51875a590759092137b2Tony Mantler            boolean handled = false;
47641e6b178ef361cdadcf27b8074e71b624df8fe3fTony Mantler            if (getCallbackFragment() instanceof OnPreferenceStartFragmentCallback) {
47741e6b178ef361cdadcf27b8074e71b624df8fe3fTony Mantler                handled = ((OnPreferenceStartFragmentCallback) getCallbackFragment())
478c4868c8a2946a038466f51875a590759092137b2Tony Mantler                        .onPreferenceStartFragment(this, preference);
479c4868c8a2946a038466f51875a590759092137b2Tony Mantler            }
480c4868c8a2946a038466f51875a590759092137b2Tony Mantler            if (!handled && getActivity() instanceof OnPreferenceStartFragmentCallback){
481c4868c8a2946a038466f51875a590759092137b2Tony Mantler                handled = ((OnPreferenceStartFragmentCallback) getActivity())
482c4868c8a2946a038466f51875a590759092137b2Tony Mantler                        .onPreferenceStartFragment(this, preference);
483c4868c8a2946a038466f51875a590759092137b2Tony Mantler            }
484c4868c8a2946a038466f51875a590759092137b2Tony Mantler            return handled;
4856904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        }
4866904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        return false;
4876904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
4886904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
4896904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    /**
4906904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * Called by
4916904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * {@link android.support.v7.preference.PreferenceScreen#onClick()} in order to navigate to a
4926904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * new screen of preferences. Calls
4936904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * {@link PreferenceFragment.OnPreferenceStartScreenCallback#onPreferenceStartScreen}
494c4868c8a2946a038466f51875a590759092137b2Tony Mantler     * if the target fragment or containing activity implements
4956904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * {@link PreferenceFragment.OnPreferenceStartScreenCallback}.
4966904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * @param preferenceScreen The {@link android.support.v7.preference.PreferenceScreen} to
4976904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     *                         navigate to.
4986904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     */
4996904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    @Override
5006904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    public void onNavigateToScreen(PreferenceScreen preferenceScreen) {
501bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler        boolean handled = false;
50241e6b178ef361cdadcf27b8074e71b624df8fe3fTony Mantler        if (getCallbackFragment() instanceof OnPreferenceStartScreenCallback) {
50341e6b178ef361cdadcf27b8074e71b624df8fe3fTony Mantler            handled = ((OnPreferenceStartScreenCallback) getCallbackFragment())
504bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler                    .onPreferenceStartScreen(this, preferenceScreen);
505bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler        }
506bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler        if (!handled && getActivity() instanceof OnPreferenceStartScreenCallback) {
507bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler            ((OnPreferenceStartScreenCallback) getActivity())
508bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler                    .onPreferenceStartScreen(this, preferenceScreen);
5096904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        }
5106904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
5116904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
5126904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    /**
5136904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * Finds a {@link Preference} based on its key.
5146904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     *
5156904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * @param key The key of the preference to retrieve.
5166904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * @return The {@link Preference} with the key, or null.
5176904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * @see android.support.v7.preference.PreferenceGroup#findPreference(CharSequence)
5186904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     */
5196904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    public Preference findPreference(CharSequence key) {
5206904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        if (mPreferenceManager == null) {
5216904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            return null;
5226904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        }
5236904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        return mPreferenceManager.findPreference(key);
5246904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
5256904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
5266904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    private void requirePreferenceManager() {
5276904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        if (mPreferenceManager == null) {
5286904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            throw new RuntimeException("This should be called after super.onCreate.");
5296904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        }
5306904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
5316904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
5326904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    private void postBindPreferences() {
5336904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        if (mHandler.hasMessages(MSG_BIND_PREFERENCES)) return;
5346904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        mHandler.obtainMessage(MSG_BIND_PREFERENCES).sendToTarget();
5356904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
5366904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
5376904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    private void bindPreferences() {
5386904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        final PreferenceScreen preferenceScreen = getPreferenceScreen();
5396904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        if (preferenceScreen != null) {
54053b6dca0375b0b40d968f9e9d3dabda3e958fc41Tony Mantler            getListView().setAdapter(onCreateAdapter(preferenceScreen));
541e61b4475e1837034d8926593aff9d35f8dfaebe2Tony Mantler            preferenceScreen.onAttached();
5426904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        }
5436904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        onBindPreferences();
5446904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
5456904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
5468f7f0d48fac8f83e90a04ba67f9a03f93c6ed262Jason Monk    private void unbindPreferences() {
5478f7f0d48fac8f83e90a04ba67f9a03f93c6ed262Jason Monk        final PreferenceScreen preferenceScreen = getPreferenceScreen();
5488f7f0d48fac8f83e90a04ba67f9a03f93c6ed262Jason Monk        if (preferenceScreen != null) {
5498f7f0d48fac8f83e90a04ba67f9a03f93c6ed262Jason Monk            preferenceScreen.onDetached();
5508f7f0d48fac8f83e90a04ba67f9a03f93c6ed262Jason Monk        }
5518f7f0d48fac8f83e90a04ba67f9a03f93c6ed262Jason Monk        onUnbindPreferences();
5528f7f0d48fac8f83e90a04ba67f9a03f93c6ed262Jason Monk    }
5538f7f0d48fac8f83e90a04ba67f9a03f93c6ed262Jason Monk
5546904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    /** @hide */
5556904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    protected void onBindPreferences() {
5566904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
5576904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
5586904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    /** @hide */
5596904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    protected void onUnbindPreferences() {
5606904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
5616904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
5626904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    public final RecyclerView getListView() {
5636904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        return mList;
5646904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
5656904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
5666904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    /**
5676904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * Creates the {@link android.support.v7.widget.RecyclerView} used to display the preferences.
5686904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * Subclasses may override this to return a customized
5696904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * {@link android.support.v7.widget.RecyclerView}.
5706904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * @param inflater The LayoutInflater object that can be used to inflate the
5716904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     *                 {@link android.support.v7.widget.RecyclerView}.
5726904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * @param parent The parent {@link android.view.View} that the RecyclerView will be attached to.
5736904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     *               This method should not add the view itself, but this can be used to generate
5746904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     *               the LayoutParams of the view.
5756904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * @param savedInstanceState If non-null, this view is being re-constructed from a previous
5766904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     *                           saved state as given here
5776904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * @return A new RecyclerView object to be placed into the view hierarchy
5786904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     */
5796904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    public RecyclerView onCreateRecyclerView(LayoutInflater inflater, ViewGroup parent,
5806904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            Bundle savedInstanceState) {
5816904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        RecyclerView recyclerView = (RecyclerView) inflater
5826759b1021d8198ad1d239bb30e5a102b99624bceAdam Lesinski                .inflate(android.support.v7.preference.R.layout.preference_recyclerview,
5836759b1021d8198ad1d239bb30e5a102b99624bceAdam Lesinski                        parent, false);
5846904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
5856904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        recyclerView.setLayoutManager(onCreateLayoutManager());
5861553af7799b550e0821a5e579db0bccf1f0835b8Steven Dao        recyclerView.setAccessibilityDelegateCompat(
5871553af7799b550e0821a5e579db0bccf1f0835b8Steven Dao                new PreferenceRecyclerViewAccessibilityDelegate(recyclerView));
5886904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
5896904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        return recyclerView;
5906904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
5916904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
5926904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    /**
5936904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * Called from {@link #onCreateRecyclerView} to create the
5946904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * {@link android.support.v7.widget.RecyclerView.LayoutManager} for the created
5956904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * {@link android.support.v7.widget.RecyclerView}.
5966904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * @return A new {@link android.support.v7.widget.RecyclerView.LayoutManager} instance.
5976904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     */
5986904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    public RecyclerView.LayoutManager onCreateLayoutManager() {
5996904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        return new LinearLayoutManager(getActivity());
6006904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
6016904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
6026904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    /**
60353b6dca0375b0b40d968f9e9d3dabda3e958fc41Tony Mantler     * Creates the root adapter.
60453b6dca0375b0b40d968f9e9d3dabda3e958fc41Tony Mantler     *
60553b6dca0375b0b40d968f9e9d3dabda3e958fc41Tony Mantler     * @param preferenceScreen Preference screen object to create the adapter for.
60653b6dca0375b0b40d968f9e9d3dabda3e958fc41Tony Mantler     * @return An adapter that contains the preferences contained in this {@link PreferenceScreen}.
60753b6dca0375b0b40d968f9e9d3dabda3e958fc41Tony Mantler     */
60853b6dca0375b0b40d968f9e9d3dabda3e958fc41Tony Mantler    protected RecyclerView.Adapter onCreateAdapter(PreferenceScreen preferenceScreen) {
60953b6dca0375b0b40d968f9e9d3dabda3e958fc41Tony Mantler        return new PreferenceGroupAdapter(preferenceScreen);
61053b6dca0375b0b40d968f9e9d3dabda3e958fc41Tony Mantler    }
61153b6dca0375b0b40d968f9e9d3dabda3e958fc41Tony Mantler
61253b6dca0375b0b40d968f9e9d3dabda3e958fc41Tony Mantler    /**
6136904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * Called when a preference in the tree requests to display a dialog. Subclasses should
6146904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * override this method to display custom dialogs or to handle dialogs for custom preference
6156904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * classes.
6166904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     *
6176904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     * @param preference The Preference object requesting the dialog.
6186904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler     */
6196904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    @Override
6206904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    public void onDisplayPreferenceDialog(Preference preference) {
621bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler
622bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler        boolean handled = false;
62341e6b178ef361cdadcf27b8074e71b624df8fe3fTony Mantler        if (getCallbackFragment() instanceof OnPreferenceDisplayDialogCallback) {
62441e6b178ef361cdadcf27b8074e71b624df8fe3fTony Mantler            handled = ((OnPreferenceDisplayDialogCallback) getCallbackFragment())
625bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler                    .onPreferenceDisplayDialog(this, preference);
626bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler        }
627bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler        if (!handled && getActivity() instanceof OnPreferenceDisplayDialogCallback) {
628bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler            handled = ((OnPreferenceDisplayDialogCallback) getActivity())
629bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler                    .onPreferenceDisplayDialog(this, preference);
630bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler        }
631bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler
632bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler        if (handled) {
633bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler            return;
634bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler        }
635bd4cbab53c68c95f62407cf872b7155a520748a0Tony Mantler
6366904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        // check if dialog is already showing
6376904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        if (getFragmentManager().findFragmentByTag(DIALOG_FRAGMENT_TAG) != null) {
6386904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            return;
6396904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        }
6406904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
6416904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        final DialogFragment f;
6426904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        if (preference instanceof EditTextPreference) {
6436904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            f = EditTextPreferenceDialogFragment.newInstance(preference.getKey());
6446904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        } else if (preference instanceof ListPreference) {
6456904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            f = ListPreferenceDialogFragment.newInstance(preference.getKey());
6460112bacf4aa212f4d0da45594a88694f295ae56cTony Mantler        } else if (preference instanceof MultiSelectListPreference) {
6470112bacf4aa212f4d0da45594a88694f295ae56cTony Mantler            f = MultiSelectListPreferenceDialogFragment.newInstance(preference.getKey());
6486904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        } else {
6496904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler            throw new IllegalArgumentException("Tried to display dialog for unknown " +
6506904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler                    "preference type. Did you forget to override onDisplayPreferenceDialog()?");
6516904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        }
6526904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        f.setTargetFragment(this, 0);
6536904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler        f.show(getFragmentManager(), DIALOG_FRAGMENT_TAG);
6546904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler    }
6556904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler
65641e6b178ef361cdadcf27b8074e71b624df8fe3fTony Mantler    /**
65741e6b178ef361cdadcf27b8074e71b624df8fe3fTony Mantler     * Basically a wrapper for getParentFragment which is v17+. Used by the leanback preference lib.
65841e6b178ef361cdadcf27b8074e71b624df8fe3fTony Mantler     * @return Fragment to possibly use as a callback
65941e6b178ef361cdadcf27b8074e71b624df8fe3fTony Mantler     * @hide
66041e6b178ef361cdadcf27b8074e71b624df8fe3fTony Mantler     */
66141e6b178ef361cdadcf27b8074e71b624df8fe3fTony Mantler    public Fragment getCallbackFragment() {
66241e6b178ef361cdadcf27b8074e71b624df8fe3fTony Mantler        return null;
66341e6b178ef361cdadcf27b8074e71b624df8fe3fTony Mantler    }
6641fcd004668b5a9038c312e4426031027d8641353Tony Mantler
66566222008cbda61251014caf1442930a48561d25cTony Mantler    public void scrollToPreference(final String key) {
66666222008cbda61251014caf1442930a48561d25cTony Mantler        scrollToPreferenceInternal(null, key);
66766222008cbda61251014caf1442930a48561d25cTony Mantler    }
66866222008cbda61251014caf1442930a48561d25cTony Mantler
66966222008cbda61251014caf1442930a48561d25cTony Mantler    public void scrollToPreference(final Preference preference) {
67066222008cbda61251014caf1442930a48561d25cTony Mantler        scrollToPreferenceInternal(preference, null);
67166222008cbda61251014caf1442930a48561d25cTony Mantler    }
67266222008cbda61251014caf1442930a48561d25cTony Mantler
67366222008cbda61251014caf1442930a48561d25cTony Mantler    private void scrollToPreferenceInternal(final Preference preference, final String key) {
67466222008cbda61251014caf1442930a48561d25cTony Mantler        final Runnable r = new Runnable() {
67566222008cbda61251014caf1442930a48561d25cTony Mantler            @Override
67666222008cbda61251014caf1442930a48561d25cTony Mantler            public void run() {
67766222008cbda61251014caf1442930a48561d25cTony Mantler                final RecyclerView.Adapter adapter = mList.getAdapter();
67866222008cbda61251014caf1442930a48561d25cTony Mantler                if (!(adapter instanceof
67966222008cbda61251014caf1442930a48561d25cTony Mantler                        PreferenceGroup.PreferencePositionCallback)) {
68066222008cbda61251014caf1442930a48561d25cTony Mantler                    if (adapter != null) {
68166222008cbda61251014caf1442930a48561d25cTony Mantler                        throw new IllegalStateException("Adapter must implement "
68266222008cbda61251014caf1442930a48561d25cTony Mantler                                + "PreferencePositionCallback");
68366222008cbda61251014caf1442930a48561d25cTony Mantler                    } else {
68466222008cbda61251014caf1442930a48561d25cTony Mantler                        // Adapter was set to null, so don't scroll I guess?
68566222008cbda61251014caf1442930a48561d25cTony Mantler                        return;
68666222008cbda61251014caf1442930a48561d25cTony Mantler                    }
68766222008cbda61251014caf1442930a48561d25cTony Mantler                }
68866222008cbda61251014caf1442930a48561d25cTony Mantler                final int position;
68966222008cbda61251014caf1442930a48561d25cTony Mantler                if (preference != null) {
69066222008cbda61251014caf1442930a48561d25cTony Mantler                    position = ((PreferenceGroup.PreferencePositionCallback) adapter)
69166222008cbda61251014caf1442930a48561d25cTony Mantler                            .getPreferenceAdapterPosition(preference);
69266222008cbda61251014caf1442930a48561d25cTony Mantler                } else {
69366222008cbda61251014caf1442930a48561d25cTony Mantler                    position = ((PreferenceGroup.PreferencePositionCallback) adapter)
69466222008cbda61251014caf1442930a48561d25cTony Mantler                            .getPreferenceAdapterPosition(key);
69566222008cbda61251014caf1442930a48561d25cTony Mantler                }
69666222008cbda61251014caf1442930a48561d25cTony Mantler                if (position != RecyclerView.NO_POSITION) {
69766222008cbda61251014caf1442930a48561d25cTony Mantler                    mList.scrollToPosition(position);
69866222008cbda61251014caf1442930a48561d25cTony Mantler                } else {
69966222008cbda61251014caf1442930a48561d25cTony Mantler                    // Item not found, wait for an update and try again
70066222008cbda61251014caf1442930a48561d25cTony Mantler                    adapter.registerAdapterDataObserver(
70166222008cbda61251014caf1442930a48561d25cTony Mantler                            new ScrollToPreferenceObserver(adapter, mList, preference, key));
70266222008cbda61251014caf1442930a48561d25cTony Mantler                }
70366222008cbda61251014caf1442930a48561d25cTony Mantler            }
70466222008cbda61251014caf1442930a48561d25cTony Mantler        };
70566222008cbda61251014caf1442930a48561d25cTony Mantler        if (mList == null) {
70666222008cbda61251014caf1442930a48561d25cTony Mantler            mSelectPreferenceRunnable = r;
70766222008cbda61251014caf1442930a48561d25cTony Mantler        } else {
70866222008cbda61251014caf1442930a48561d25cTony Mantler            r.run();
70966222008cbda61251014caf1442930a48561d25cTony Mantler        }
71066222008cbda61251014caf1442930a48561d25cTony Mantler    }
71166222008cbda61251014caf1442930a48561d25cTony Mantler
71266222008cbda61251014caf1442930a48561d25cTony Mantler    private static class ScrollToPreferenceObserver extends RecyclerView.AdapterDataObserver {
71366222008cbda61251014caf1442930a48561d25cTony Mantler        private final RecyclerView.Adapter mAdapter;
71466222008cbda61251014caf1442930a48561d25cTony Mantler        private final RecyclerView mList;
71566222008cbda61251014caf1442930a48561d25cTony Mantler        private final Preference mPreference;
71666222008cbda61251014caf1442930a48561d25cTony Mantler        private final String mKey;
71766222008cbda61251014caf1442930a48561d25cTony Mantler
71866222008cbda61251014caf1442930a48561d25cTony Mantler        public ScrollToPreferenceObserver(RecyclerView.Adapter adapter, RecyclerView list,
71966222008cbda61251014caf1442930a48561d25cTony Mantler                Preference preference, String key) {
72066222008cbda61251014caf1442930a48561d25cTony Mantler            mAdapter = adapter;
72166222008cbda61251014caf1442930a48561d25cTony Mantler            mList = list;
72266222008cbda61251014caf1442930a48561d25cTony Mantler            mPreference = preference;
72366222008cbda61251014caf1442930a48561d25cTony Mantler            mKey = key;
72466222008cbda61251014caf1442930a48561d25cTony Mantler        }
72566222008cbda61251014caf1442930a48561d25cTony Mantler
72666222008cbda61251014caf1442930a48561d25cTony Mantler        private void scrollToPreference() {
72766222008cbda61251014caf1442930a48561d25cTony Mantler            mAdapter.unregisterAdapterDataObserver(this);
72866222008cbda61251014caf1442930a48561d25cTony Mantler            final int position;
72966222008cbda61251014caf1442930a48561d25cTony Mantler            if (mPreference != null) {
73066222008cbda61251014caf1442930a48561d25cTony Mantler                position = ((PreferenceGroup.PreferencePositionCallback) mAdapter)
73166222008cbda61251014caf1442930a48561d25cTony Mantler                        .getPreferenceAdapterPosition(mPreference);
73266222008cbda61251014caf1442930a48561d25cTony Mantler            } else {
73366222008cbda61251014caf1442930a48561d25cTony Mantler                position = ((PreferenceGroup.PreferencePositionCallback) mAdapter)
73466222008cbda61251014caf1442930a48561d25cTony Mantler                        .getPreferenceAdapterPosition(mKey);
73566222008cbda61251014caf1442930a48561d25cTony Mantler            }
73666222008cbda61251014caf1442930a48561d25cTony Mantler            if (position != RecyclerView.NO_POSITION) {
73766222008cbda61251014caf1442930a48561d25cTony Mantler                mList.scrollToPosition(position);
73866222008cbda61251014caf1442930a48561d25cTony Mantler            }
73966222008cbda61251014caf1442930a48561d25cTony Mantler        }
74066222008cbda61251014caf1442930a48561d25cTony Mantler
74166222008cbda61251014caf1442930a48561d25cTony Mantler        @Override
74266222008cbda61251014caf1442930a48561d25cTony Mantler        public void onChanged() {
74366222008cbda61251014caf1442930a48561d25cTony Mantler            scrollToPreference();
74466222008cbda61251014caf1442930a48561d25cTony Mantler        }
74566222008cbda61251014caf1442930a48561d25cTony Mantler
74666222008cbda61251014caf1442930a48561d25cTony Mantler        @Override
74766222008cbda61251014caf1442930a48561d25cTony Mantler        public void onItemRangeChanged(int positionStart, int itemCount) {
74866222008cbda61251014caf1442930a48561d25cTony Mantler            scrollToPreference();
74966222008cbda61251014caf1442930a48561d25cTony Mantler        }
75066222008cbda61251014caf1442930a48561d25cTony Mantler
75166222008cbda61251014caf1442930a48561d25cTony Mantler        @Override
75266222008cbda61251014caf1442930a48561d25cTony Mantler        public void onItemRangeChanged(int positionStart, int itemCount, Object payload) {
75366222008cbda61251014caf1442930a48561d25cTony Mantler            scrollToPreference();
75466222008cbda61251014caf1442930a48561d25cTony Mantler        }
75566222008cbda61251014caf1442930a48561d25cTony Mantler
75666222008cbda61251014caf1442930a48561d25cTony Mantler        @Override
75766222008cbda61251014caf1442930a48561d25cTony Mantler        public void onItemRangeInserted(int positionStart, int itemCount) {
75866222008cbda61251014caf1442930a48561d25cTony Mantler            scrollToPreference();
75966222008cbda61251014caf1442930a48561d25cTony Mantler        }
76066222008cbda61251014caf1442930a48561d25cTony Mantler
76166222008cbda61251014caf1442930a48561d25cTony Mantler        @Override
76266222008cbda61251014caf1442930a48561d25cTony Mantler        public void onItemRangeRemoved(int positionStart, int itemCount) {
76366222008cbda61251014caf1442930a48561d25cTony Mantler            scrollToPreference();
76466222008cbda61251014caf1442930a48561d25cTony Mantler        }
76566222008cbda61251014caf1442930a48561d25cTony Mantler
76666222008cbda61251014caf1442930a48561d25cTony Mantler        @Override
76766222008cbda61251014caf1442930a48561d25cTony Mantler        public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
76866222008cbda61251014caf1442930a48561d25cTony Mantler            scrollToPreference();
76966222008cbda61251014caf1442930a48561d25cTony Mantler        }
77066222008cbda61251014caf1442930a48561d25cTony Mantler    }
77166222008cbda61251014caf1442930a48561d25cTony Mantler
7721fcd004668b5a9038c312e4426031027d8641353Tony Mantler    private class DividerDecoration extends RecyclerView.ItemDecoration {
7731fcd004668b5a9038c312e4426031027d8641353Tony Mantler
7741fcd004668b5a9038c312e4426031027d8641353Tony Mantler        private Drawable mDivider;
7751fcd004668b5a9038c312e4426031027d8641353Tony Mantler        private int mDividerHeight;
7761fcd004668b5a9038c312e4426031027d8641353Tony Mantler
7771fcd004668b5a9038c312e4426031027d8641353Tony Mantler        @Override
7781fcd004668b5a9038c312e4426031027d8641353Tony Mantler        public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
7791fcd004668b5a9038c312e4426031027d8641353Tony Mantler            if (mDivider == null) {
7801fcd004668b5a9038c312e4426031027d8641353Tony Mantler                return;
7811fcd004668b5a9038c312e4426031027d8641353Tony Mantler            }
7821fcd004668b5a9038c312e4426031027d8641353Tony Mantler            final int childCount = parent.getChildCount();
7831fcd004668b5a9038c312e4426031027d8641353Tony Mantler            final int width = parent.getWidth();
7841fcd004668b5a9038c312e4426031027d8641353Tony Mantler            for (int childViewIndex = 0; childViewIndex < childCount; childViewIndex++) {
7851fcd004668b5a9038c312e4426031027d8641353Tony Mantler                final View view = parent.getChildAt(childViewIndex);
7861fcd004668b5a9038c312e4426031027d8641353Tony Mantler                if (shouldDrawDividerBelow(view, parent)) {
7871fcd004668b5a9038c312e4426031027d8641353Tony Mantler                    int top = (int) ViewCompat.getY(view) + view.getHeight();
7881fcd004668b5a9038c312e4426031027d8641353Tony Mantler                    mDivider.setBounds(0, top, width, top + mDividerHeight);
7891fcd004668b5a9038c312e4426031027d8641353Tony Mantler                    mDivider.draw(c);
7901fcd004668b5a9038c312e4426031027d8641353Tony Mantler                }
7911fcd004668b5a9038c312e4426031027d8641353Tony Mantler            }
7921fcd004668b5a9038c312e4426031027d8641353Tony Mantler        }
7931fcd004668b5a9038c312e4426031027d8641353Tony Mantler
7941fcd004668b5a9038c312e4426031027d8641353Tony Mantler        @Override
7951fcd004668b5a9038c312e4426031027d8641353Tony Mantler        public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
7961fcd004668b5a9038c312e4426031027d8641353Tony Mantler                RecyclerView.State state) {
7971fcd004668b5a9038c312e4426031027d8641353Tony Mantler            if (shouldDrawDividerBelow(view, parent)) {
7981fcd004668b5a9038c312e4426031027d8641353Tony Mantler                outRect.bottom = mDividerHeight;
7991fcd004668b5a9038c312e4426031027d8641353Tony Mantler            }
8001fcd004668b5a9038c312e4426031027d8641353Tony Mantler        }
8011fcd004668b5a9038c312e4426031027d8641353Tony Mantler
8021fcd004668b5a9038c312e4426031027d8641353Tony Mantler        private boolean shouldDrawDividerBelow(View view, RecyclerView parent) {
803446e2ab0a44e2515218540f38672987188287aa2Maurice Lam            final RecyclerView.ViewHolder holder = parent.getChildViewHolder(view);
804446e2ab0a44e2515218540f38672987188287aa2Maurice Lam            final boolean dividerAllowedBelow = holder instanceof PreferenceViewHolder
805446e2ab0a44e2515218540f38672987188287aa2Maurice Lam                    && ((PreferenceViewHolder) holder).isDividerAllowedBelow();
806446e2ab0a44e2515218540f38672987188287aa2Maurice Lam            if (!dividerAllowedBelow) {
807446e2ab0a44e2515218540f38672987188287aa2Maurice Lam                return false;
808446e2ab0a44e2515218540f38672987188287aa2Maurice Lam            }
8091fcd004668b5a9038c312e4426031027d8641353Tony Mantler            boolean nextAllowed = true;
8101fcd004668b5a9038c312e4426031027d8641353Tony Mantler            int index = parent.indexOfChild(view);
8111fcd004668b5a9038c312e4426031027d8641353Tony Mantler            if (index < parent.getChildCount() - 1) {
8121fcd004668b5a9038c312e4426031027d8641353Tony Mantler                final View nextView = parent.getChildAt(index + 1);
813446e2ab0a44e2515218540f38672987188287aa2Maurice Lam                final RecyclerView.ViewHolder nextHolder = parent.getChildViewHolder(nextView);
814446e2ab0a44e2515218540f38672987188287aa2Maurice Lam                nextAllowed = nextHolder instanceof PreferenceViewHolder
815446e2ab0a44e2515218540f38672987188287aa2Maurice Lam                        && ((PreferenceViewHolder) nextHolder).isDividerAllowedAbove();
8161fcd004668b5a9038c312e4426031027d8641353Tony Mantler            }
817446e2ab0a44e2515218540f38672987188287aa2Maurice Lam            return nextAllowed;
8181fcd004668b5a9038c312e4426031027d8641353Tony Mantler        }
8191fcd004668b5a9038c312e4426031027d8641353Tony Mantler
8201fcd004668b5a9038c312e4426031027d8641353Tony Mantler        public void setDivider(Drawable divider) {
8211fcd004668b5a9038c312e4426031027d8641353Tony Mantler            if (divider != null) {
8221fcd004668b5a9038c312e4426031027d8641353Tony Mantler                mDividerHeight = divider.getIntrinsicHeight();
8231fcd004668b5a9038c312e4426031027d8641353Tony Mantler            } else {
8241fcd004668b5a9038c312e4426031027d8641353Tony Mantler                mDividerHeight = 0;
8251fcd004668b5a9038c312e4426031027d8641353Tony Mantler            }
8261fcd004668b5a9038c312e4426031027d8641353Tony Mantler            mDivider = divider;
8271fcd004668b5a9038c312e4426031027d8641353Tony Mantler            mList.invalidateItemDecorations();
8281fcd004668b5a9038c312e4426031027d8641353Tony Mantler        }
8291fcd004668b5a9038c312e4426031027d8641353Tony Mantler
8301fcd004668b5a9038c312e4426031027d8641353Tony Mantler        public void setDividerHeight(int dividerHeight) {
8311fcd004668b5a9038c312e4426031027d8641353Tony Mantler            mDividerHeight = dividerHeight;
8321fcd004668b5a9038c312e4426031027d8641353Tony Mantler            mList.invalidateItemDecorations();
8331fcd004668b5a9038c312e4426031027d8641353Tony Mantler        }
8341fcd004668b5a9038c312e4426031027d8641353Tony Mantler    }
8356904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler}
836