java.lang.Object

↳android.app.Fragment

↳androidx.preference.PreferenceFragment

Subclasses:

BaseLeanbackPreferenceFragment, LeanbackPreferenceFragment

Gradle dependencies

compile group: 'androidx.preference', name: 'preference', version: '1.2.0'

  • groupId: androidx.preference
  • artifactId: preference
  • version: 1.2.0

Artifact androidx.preference:preference:1.2.0 it located at Google repository (https://maven.google.com/)

Androidx artifact mapping:

androidx.preference:preference com.android.support:preference-v7

Androidx class mapping:

androidx.preference.PreferenceFragment android.support.v14.preference.PreferenceFragment

Overview

Shows a hierarchy of Preference objects as lists. These preferences will automatically save to android.content.SharedPreferences as the user interacts with them. To retrieve an instance of android.content.SharedPreferences that the preference hierarchy in this fragment will use, call PreferenceManager with a context in the same package as this fragment.

Furthermore, the preferences shown will follow the visual style of system preferences. It is easy to create a hierarchy of preferences (that can be shown on multiple screens) via XML. For these reasons, it is recommended to use this fragment (as a superclass) to deal with preferences in applications.

A PreferenceScreen object should be at the top of the preference hierarchy. Furthermore, subsequent PreferenceScreen in the hierarchy denote a screen break--that is the preferences contained within subsequent PreferenceScreen should be shown on another screen. The preference framework handles this by calling PreferenceFragment.onNavigateToScreen(PreferenceScreen).

The preference hierarchy can be formed in multiple ways:

  • From an XML file specifying the hierarchy
  • From different that each specify its own preferences in an XML file via meta-data
  • From an object hierarchy rooted with PreferenceScreen

To inflate from XML, use the PreferenceFragment.addPreferencesFromResource(int). The root element should be a PreferenceScreen. Subsequent elements can point to actual Preference subclasses. As mentioned above, subsequent PreferenceScreen in the hierarchy will result in the screen break.

To specify an object hierarchy rooted with PreferenceScreen, use PreferenceFragment.setPreferenceScreen(PreferenceScreen).

As a convenience, this fragment implements a click listener for any preference in the current hierarchy, see PreferenceFragment.onPreferenceTreeClick(Preference).

Developer Guides

For information about building a settings screen using the AndroidX Preference library, see Settings.

Summary

Fields
public static final java.lang.StringARG_PREFERENCE_ROOT

Fragment argument used to specify the tag of the desired root PreferenceScreen object.

Constructors
publicPreferenceFragment()

Methods
public voidaddPreferencesFromResource(int preferencesResId)

Inflates the given XML resource and adds the preference hierarchy to the current preference hierarchy.

public PreferencefindPreference(java.lang.CharSequence key)

Finds a Preference based on its key.

public android.app.FragmentgetCallbackFragment()

A wrapper for getParentFragment which is v17+.

public final RecyclerViewgetListView()

public PreferenceManagergetPreferenceManager()

Returns the PreferenceManager used by this fragment.

public PreferenceScreengetPreferenceScreen()

Gets the root of the preference hierarchy that this fragment is showing.

protected voidonBindPreferences()

public voidonCreate(Bundle savedInstanceState)

protected RecyclerView.AdapteronCreateAdapter(PreferenceScreen preferenceScreen)

Creates the root adapter.

public RecyclerView.LayoutManageronCreateLayoutManager()

Called from PreferenceFragment.onCreateRecyclerView(LayoutInflater, ViewGroup, Bundle) to create the for the created RecyclerView.

public abstract voidonCreatePreferences(Bundle savedInstanceState, java.lang.String rootKey)

Called during PreferenceFragment.onCreate(Bundle) to supply the preferences for this fragment.

public RecyclerViewonCreateRecyclerView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState)

Creates the RecyclerView used to display the preferences.

public ViewonCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)

public voidonDestroyView()

public voidonDisplayPreferenceDialog(Preference preference)

Called when a preference in the tree requests to display a dialog.

public voidonNavigateToScreen(PreferenceScreen preferenceScreen)

Called by PreferenceScreen.onClick() in order to navigate to a new screen of preferences.

public booleanonPreferenceTreeClick(Preference preference)

public voidonSaveInstanceState(Bundle outState)

public voidonStart()

public voidonStop()

protected voidonUnbindPreferences()

public voidonViewCreated(View view, Bundle savedInstanceState)

public voidscrollToPreference(Preference preference)

public voidscrollToPreference(java.lang.String key)

public voidsetDivider(Drawable divider)

Sets the Drawable that will be drawn between each item in the list.

public voidsetDividerHeight(int height)

Sets the height of the divider that will be drawn between each item in the list.

public voidsetPreferenceScreen(PreferenceScreen preferenceScreen)

Sets the root of the preference hierarchy that this fragment is showing.

public voidsetPreferencesFromResource(int preferencesResId, java.lang.String key)

Inflates the given XML resource and replaces the current preference hierarchy (if any) with the preference hierarchy rooted at key.

from java.lang.Objectclone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

Fields

public static final java.lang.String ARG_PREFERENCE_ROOT

Deprecated: Use PreferenceFragmentCompat instead

Fragment argument used to specify the tag of the desired root PreferenceScreen object.

Constructors

public PreferenceFragment()

Methods

public void onCreate(Bundle savedInstanceState)

public abstract void onCreatePreferences(Bundle savedInstanceState, java.lang.String rootKey)

Deprecated: Use PreferenceFragmentCompat instead

Called during PreferenceFragment.onCreate(Bundle) to supply the preferences for this fragment. Subclasses are expected to call PreferenceFragment.setPreferenceScreen(PreferenceScreen) either directly or via helper methods such as PreferenceFragment.addPreferencesFromResource(int).

Parameters:

savedInstanceState: If the fragment is being re-created from a previous saved state, this is the state.
rootKey: If non-null, this preference fragment should be rooted at the PreferenceScreen with this key.

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)

public void setDivider(Drawable divider)

Deprecated: Use PreferenceFragmentCompat instead

Sets the Drawable that will be drawn between each item in the list.

Note: If the drawable does not have an intrinsic height, you should also call PreferenceFragment.setDividerHeight(int).

Parameters:

divider: The drawable to use

public void setDividerHeight(int height)

Deprecated: Use PreferenceFragmentCompat instead

Sets the height of the divider that will be drawn between each item in the list. Calling this will override the intrinsic height as set by PreferenceFragment.setDivider(Drawable).

Parameters:

height: The new height of the divider in pixels

public void onViewCreated(View view, Bundle savedInstanceState)

public void onStart()

public void onStop()

public void onDestroyView()

public void onSaveInstanceState(Bundle outState)

public PreferenceManager getPreferenceManager()

Deprecated: Use PreferenceFragmentCompat instead

Returns the PreferenceManager used by this fragment.

Returns:

The PreferenceManager used by this fragment

public void setPreferenceScreen(PreferenceScreen preferenceScreen)

Deprecated: Use PreferenceFragmentCompat instead

Sets the root of the preference hierarchy that this fragment is showing.

Parameters:

preferenceScreen: The root PreferenceScreen of the preference hierarchy

public PreferenceScreen getPreferenceScreen()

Deprecated: Use PreferenceFragmentCompat instead

Gets the root of the preference hierarchy that this fragment is showing.

Returns:

The PreferenceScreen that is the root of the preference hierarchy

public void addPreferencesFromResource(int preferencesResId)

Deprecated: Use PreferenceFragmentCompat instead

Inflates the given XML resource and adds the preference hierarchy to the current preference hierarchy.

Parameters:

preferencesResId: The XML resource ID to inflate

public void setPreferencesFromResource(int preferencesResId, java.lang.String key)

Deprecated: Use PreferenceFragmentCompat instead

Inflates the given XML resource and replaces the current preference hierarchy (if any) with the preference hierarchy rooted at key.

Parameters:

preferencesResId: The XML resource ID to inflate
key: The preference key of the PreferenceScreen to use as the root of the preference hierarchy, or null to use the root PreferenceScreen.

public boolean onPreferenceTreeClick(Preference preference)

Deprecated: Use PreferenceFragmentCompat instead

public void onNavigateToScreen(PreferenceScreen preferenceScreen)

Deprecated: Use PreferenceFragmentCompat instead

Called by PreferenceScreen.onClick() in order to navigate to a new screen of preferences. Calls PreferenceFragment.OnPreferenceStartScreenCallback.onPreferenceStartScreen(PreferenceFragment, PreferenceScreen) if the target fragment or containing activity implements PreferenceFragment.OnPreferenceStartScreenCallback.

Parameters:

preferenceScreen: The PreferenceScreen to navigate to

public Preference findPreference(java.lang.CharSequence key)

Deprecated: Use PreferenceFragmentCompat instead

Finds a Preference based on its key.

Parameters:

key: The key of the preference to retrieve

Returns:

The Preference with the key, or null

See also: PreferenceGroup.findPreference(CharSequence)

protected void onBindPreferences()

protected void onUnbindPreferences()

public final RecyclerView getListView()

Deprecated: Use PreferenceFragmentCompat instead

public RecyclerView onCreateRecyclerView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState)

Deprecated: Use PreferenceFragmentCompat instead

Creates the RecyclerView used to display the preferences. Subclasses may override this to return a customized RecyclerView.

Parameters:

inflater: The LayoutInflater object that can be used to inflate the RecyclerView.
parent: The parent view that the RecyclerView will be attached to. This method should not add the view itself, but this can be used to generate the layout params of the view.
savedInstanceState: If non-null, this view is being re-constructed from a previous saved state as given here.

Returns:

A new RecyclerView object to be placed into the view hierarchy

public RecyclerView.LayoutManager onCreateLayoutManager()

Deprecated: Use PreferenceFragmentCompat instead

Called from PreferenceFragment.onCreateRecyclerView(LayoutInflater, ViewGroup, Bundle) to create the for the created RecyclerView.

Returns:

A new instance

protected RecyclerView.Adapter onCreateAdapter(PreferenceScreen preferenceScreen)

Deprecated: Use PreferenceFragmentCompat instead

Creates the root adapter.

Parameters:

preferenceScreen: The PreferenceScreen object to create the adapter for

Returns:

An adapter that contains the preferences contained in this PreferenceScreen

public void onDisplayPreferenceDialog(Preference preference)

Deprecated: Use PreferenceFragmentCompat instead

Called when a preference in the tree requests to display a dialog. Subclasses should override this method to display custom dialogs or to handle dialogs for custom preference classes.

Parameters:

preference: The Preference object requesting the dialog

public android.app.Fragment getCallbackFragment()

A wrapper for getParentFragment which is v17+. Used by the leanback preference library.

Returns:

The to possibly use as a callback

public void scrollToPreference(java.lang.String key)

Deprecated: Use PreferenceFragmentCompat instead

public void scrollToPreference(Preference preference)

Deprecated: Use PreferenceFragmentCompat instead

Source

/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package androidx.preference;

import static androidx.annotation.RestrictTo.Scope.LIBRARY;

import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.TypedValue;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
import androidx.annotation.XmlRes;
import androidx.core.content.res.TypedArrayUtils;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

/**
 * Shows a hierarchy of {@link Preference} objects as lists. These preferences will automatically
 * save to {@link android.content.SharedPreferences} as the user interacts with them. To retrieve
 * an instance of {@link android.content.SharedPreferences} that the preference hierarchy in this
 * fragment will use, call
 * {@link PreferenceManager#getDefaultSharedPreferences(android.content.Context)} with a context
 * in the same package as this fragment.
 *
 * <p>Furthermore, the preferences shown will follow the visual style of system preferences. It is
 * easy to create a hierarchy of preferences (that can be shown on multiple screens) via XML. For
 * these reasons, it is recommended to use this fragment (as a superclass) to deal with
 * preferences in applications.
 *
 * <p>A {@link PreferenceScreen} object should be at the top of the preference hierarchy.
 * Furthermore, subsequent {@link PreferenceScreen} in the hierarchy denote a screen break--that
 * is the preferences contained within subsequent {@link PreferenceScreen} should be shown on
 * another screen. The preference framework handles this by calling
 * {@link #onNavigateToScreen(PreferenceScreen)}.
 *
 * <p>The preference hierarchy can be formed in multiple ways:
 *
 * <ul>
 *   <li> From an XML file specifying the hierarchy
 *   <li> From different {@link android.app.Activity Activities} that each specify its own
 *        preferences in an XML file via {@link android.app.Activity} meta-data
 *   <li> From an object hierarchy rooted with {@link PreferenceScreen}
 * </ul>
 *
 * <p>To inflate from XML, use the {@link #addPreferencesFromResource(int)}. The root element
 * should be a {@link PreferenceScreen}. Subsequent elements can point to actual
 * {@link Preference} subclasses. As mentioned above, subsequent {@link PreferenceScreen} in the
 * hierarchy will result in the screen break.
 *
 * <p>To specify an object hierarchy rooted with {@link PreferenceScreen}, use
 * {@link #setPreferenceScreen(PreferenceScreen)}.
 *
 * <p>As a convenience, this fragment implements a click listener for any preference in the current
 * hierarchy, see {@link #onPreferenceTreeClick(Preference)}.
 *
 * <div class="special reference">
 * <h3>Developer Guides</h3>
 * <p>For information about building a settings screen using the AndroidX Preference library, see
 * <a href="{@docRoot}guide/topics/ui/settings.html">Settings</a>.</p>
 * </div>
 *
 * @see Preference
 * @see PreferenceScreen
 *
 * @deprecated Use {@link PreferenceFragmentCompat} instead
 */
@SuppressWarnings({"deprecation", "DeprecatedIsStillUsed"})
@Deprecated
public abstract class PreferenceFragment extends android.app.Fragment implements
        PreferenceManager.OnPreferenceTreeClickListener,
        PreferenceManager.OnDisplayPreferenceDialogListener,
        PreferenceManager.OnNavigateToScreenListener,
        DialogPreference.TargetFragment {

    /**
     * Fragment argument used to specify the tag of the desired root {@link PreferenceScreen}
     * object.
     *
     * @deprecated Use {@link PreferenceFragmentCompat} instead
     */
    @Deprecated
    public static final String ARG_PREFERENCE_ROOT =
            "androidx.preference.PreferenceFragmentCompat.PREFERENCE_ROOT";

    private static final String PREFERENCES_TAG = "android:preferences";

    private static final String DIALOG_FRAGMENT_TAG =
            "androidx.preference.PreferenceFragment.DIALOG";

    private static final int MSG_BIND_PREFERENCES = 1;

    private final DividerDecoration mDividerDecoration = new DividerDecoration();
    private PreferenceManager mPreferenceManager;
    RecyclerView mList;
    private boolean mHavePrefs;
    private boolean mInitDone;
    private Context mStyledContext;
    private int mLayoutResId = R.layout.preference_list_fragment;
    private Runnable mSelectPreferenceRunnable;

    @SuppressWarnings("deprecation")
    private final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(@NonNull Message msg) {
            switch (msg.what) {
                case MSG_BIND_PREFERENCES:
                    bindPreferences();
                    break;
            }
        }
    };

    private final Runnable mRequestFocus = new Runnable() {
        @Override
        public void run() {
            mList.focusableViewAvailable(mList);
        }
    };

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        final TypedValue tv = new TypedValue();
        getActivity().getTheme().resolveAttribute(R.attr.preferenceTheme, tv, true);
        int theme = tv.resourceId;
        if (theme == 0) {
            // Fallback to default theme.
            theme = R.style.PreferenceThemeOverlay;
        }
        mStyledContext = new ContextThemeWrapper(getActivity(), theme);

        mPreferenceManager = new PreferenceManager(mStyledContext);
        mPreferenceManager.setOnNavigateToScreenListener(this);
        final Bundle args = getArguments();
        final String rootKey;
        if (args != null) {
            rootKey = getArguments().getString(ARG_PREFERENCE_ROOT);
        } else {
            rootKey = null;
        }
        onCreatePreferences(savedInstanceState, rootKey);
    }

    /**
     * Called during {@link #onCreate(Bundle)} to supply the preferences for this fragment.
     * Subclasses are expected to call {@link #setPreferenceScreen(PreferenceScreen)} either
     * directly or via helper methods such as {@link #addPreferencesFromResource(int)}.
     *
     * @param savedInstanceState If the fragment is being re-created from a previous saved state,
     *                           this is the state.
     * @param rootKey            If non-null, this preference fragment should be rooted at the
     *                           {@link PreferenceScreen} with this key.
     *
     * @deprecated Use {@link PreferenceFragmentCompat} instead
     */
    @Deprecated
    public abstract void onCreatePreferences(@Nullable Bundle savedInstanceState, String rootKey);

    @NonNull
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
            @Nullable Bundle savedInstanceState) {

        TypedArray a = mStyledContext.obtainStyledAttributes(null,
                R.styleable.PreferenceFragment,
                TypedArrayUtils.getAttr(mStyledContext, R.attr.preferenceFragmentStyle,
                        AndroidResources.ANDROID_R_PREFERENCE_FRAGMENT_STYLE), 0);

        mLayoutResId = a.getResourceId(R.styleable.PreferenceFragment_android_layout, mLayoutResId);

        final Drawable divider = a.getDrawable(R.styleable.PreferenceFragment_android_divider);
        final int dividerHeight = a.getDimensionPixelSize(
                R.styleable.PreferenceFragment_android_dividerHeight, -1);
        final boolean allowDividerAfterLastItem = a.getBoolean(
                R.styleable.PreferenceFragment_allowDividerAfterLastItem, true);
        a.recycle();

        final LayoutInflater themedInflater = inflater.cloneInContext(mStyledContext);

        final View view = themedInflater.inflate(mLayoutResId, container, false);

        final View rawListContainer = view.findViewById(AndroidResources.ANDROID_R_LIST_CONTAINER);
        if (!(rawListContainer instanceof ViewGroup)) {
            throw new RuntimeException("Content has view with id attribute "
                    + "'android.R.id.list_container' that is not a ViewGroup class");
        }

        final ViewGroup listContainer = (ViewGroup) rawListContainer;

        final RecyclerView listView = onCreateRecyclerView(themedInflater, listContainer,
                savedInstanceState);
        if (listView == null) {
            throw new RuntimeException("Could not create RecyclerView");
        }

        mList = listView;

        listView.addItemDecoration(mDividerDecoration);
        setDivider(divider);
        if (dividerHeight != -1) {
            setDividerHeight(dividerHeight);
        }
        mDividerDecoration.setAllowDividerAfterLastItem(allowDividerAfterLastItem);

        // If mList isn't present in the view hierarchy, add it. mList is automatically inflated
        // on an Auto device so don't need to add it.
        if (mList.getParent() == null) {
            listContainer.addView(mList);
        }
        mHandler.post(mRequestFocus);

        return view;
    }

    /**
     * Sets the {@link Drawable} that will be drawn between each item in the list.
     *
     * <p><strong>Note:</strong> If the drawable does not have an intrinsic height, you should also
     * call {@link #setDividerHeight(int)}.
     *
     * @param divider The drawable to use
     * {@link android.R.attr#divider}
     *
     * @deprecated Use {@link PreferenceFragmentCompat} instead
     */
    @Deprecated
    public void setDivider(@Nullable Drawable divider) {
        mDividerDecoration.setDivider(divider);
    }

    /**
     * Sets the height of the divider that will be drawn between each item in the list. Calling
     * this will override the intrinsic height as set by {@link #setDivider(Drawable)}.
     *
     * @param height The new height of the divider in pixels
     * {@link android.R.attr#dividerHeight}
     *
     * @deprecated Use {@link PreferenceFragmentCompat} instead
     */
    @Deprecated
    public void setDividerHeight(int height) {
        mDividerDecoration.setDividerHeight(height);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        if (savedInstanceState != null) {
            Bundle container = savedInstanceState.getBundle(PREFERENCES_TAG);
            if (container != null) {
                final PreferenceScreen preferenceScreen = getPreferenceScreen();
                if (preferenceScreen != null) {
                    preferenceScreen.restoreHierarchyState(container);
                }
            }
        }

        if (mHavePrefs) {
            bindPreferences();
            if (mSelectPreferenceRunnable != null) {
                mSelectPreferenceRunnable.run();
                mSelectPreferenceRunnable = null;
            }
        }

        mInitDone = true;
    }

    @Override
    public void onStart() {
        super.onStart();
        mPreferenceManager.setOnPreferenceTreeClickListener(this);
        mPreferenceManager.setOnDisplayPreferenceDialogListener(this);
    }

    @Override
    public void onStop() {
        super.onStop();
        mPreferenceManager.setOnPreferenceTreeClickListener(null);
        mPreferenceManager.setOnDisplayPreferenceDialogListener(null);
    }

    @Override
    public void onDestroyView() {
        mHandler.removeCallbacks(mRequestFocus);
        mHandler.removeMessages(MSG_BIND_PREFERENCES);
        if (mHavePrefs) {
            unbindPreferences();
        }
        mList = null;
        super.onDestroyView();
    }

    @Override
    public void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);

        final PreferenceScreen preferenceScreen = getPreferenceScreen();
        if (preferenceScreen != null) {
            Bundle container = new Bundle();
            preferenceScreen.saveHierarchyState(container);
            outState.putBundle(PREFERENCES_TAG, container);
        }
    }

    /**
     * Returns the {@link PreferenceManager} used by this fragment.
     *
     * @return The {@link PreferenceManager} used by this fragment
     *
     * @deprecated Use {@link PreferenceFragmentCompat} instead
     */
    @Deprecated
    public PreferenceManager getPreferenceManager() {
        return mPreferenceManager;
    }

    /**
     * Sets the root of the preference hierarchy that this fragment is showing.
     *
     * @param preferenceScreen The root {@link PreferenceScreen} of the preference hierarchy
     *
     * @deprecated Use {@link PreferenceFragmentCompat} instead
     */
    @Deprecated
    public void setPreferenceScreen(PreferenceScreen preferenceScreen) {
        if (mPreferenceManager.setPreferences(preferenceScreen) && preferenceScreen != null) {
            onUnbindPreferences();
            mHavePrefs = true;
            if (mInitDone) {
                postBindPreferences();
            }
        }
    }

    /**
     * Gets the root of the preference hierarchy that this fragment is showing.
     *
     * @return The {@link PreferenceScreen} that is the root of the preference hierarchy
     *
     * @deprecated Use {@link PreferenceFragmentCompat} instead
     */
    @Deprecated
    public PreferenceScreen getPreferenceScreen() {
        return mPreferenceManager.getPreferenceScreen();
    }

    /**
     * Inflates the given XML resource and adds the preference hierarchy to the current
     * preference hierarchy.
     *
     * @param preferencesResId The XML resource ID to inflate
     *
     * @deprecated Use {@link PreferenceFragmentCompat} instead
     */
    @Deprecated
    public void addPreferencesFromResource(@XmlRes int preferencesResId) {
        requirePreferenceManager();

        setPreferenceScreen(mPreferenceManager.inflateFromResource(mStyledContext,
                preferencesResId, getPreferenceScreen()));
    }

    /**
     * Inflates the given XML resource and replaces the current preference hierarchy (if any) with
     * the preference hierarchy rooted at {@code key}.
     *
     * @param preferencesResId The XML resource ID to inflate
     * @param key              The preference key of the {@link PreferenceScreen} to use as the
     *                         root of the preference hierarchy, or {@code null} to use the root
     *                         {@link PreferenceScreen}.
     *
     * @deprecated Use {@link PreferenceFragmentCompat} instead
     */
    @Deprecated
    public void setPreferencesFromResource(@XmlRes int preferencesResId, @Nullable String key) {
        requirePreferenceManager();

        final PreferenceScreen xmlRoot = mPreferenceManager.inflateFromResource(mStyledContext,
                preferencesResId, null);

        final Preference root;
        if (key != null) {
            root = xmlRoot.findPreference(key);
            if (!(root instanceof PreferenceScreen)) {
                throw new IllegalArgumentException("Preference object with key " + key
                        + " is not a PreferenceScreen");
            }
        } else {
            root = xmlRoot;
        }

        setPreferenceScreen((PreferenceScreen) root);
    }

    /**
     * {@inheritDoc}
     * @deprecated Use {@link PreferenceFragmentCompat} instead
     */
    @Deprecated
    @Override
    public boolean onPreferenceTreeClick(@NonNull Preference preference) {
        if (preference.getFragment() != null) {
            boolean handled = false;
            if (getCallbackFragment() instanceof OnPreferenceStartFragmentCallback) {
                handled = ((OnPreferenceStartFragmentCallback) getCallbackFragment())
                        .onPreferenceStartFragment(this, preference);
            }
            if (!handled && getActivity() instanceof OnPreferenceStartFragmentCallback) {
                handled = ((OnPreferenceStartFragmentCallback) getActivity())
                        .onPreferenceStartFragment(this, preference);
            }
            return handled;
        }
        return false;
    }

    /**
     * Called by {@link PreferenceScreen#onClick()} in order to navigate to a new screen of
     * preferences. Calls
     * {@link PreferenceFragment.OnPreferenceStartScreenCallback#onPreferenceStartScreen} if the
     * target fragment or containing activity implements
     * {@link PreferenceFragment.OnPreferenceStartScreenCallback}.
     *
     * @param preferenceScreen The {@link PreferenceScreen} to navigate to
     *
     * @deprecated Use {@link PreferenceFragmentCompat} instead
     */
    @Deprecated
    @Override
    public void onNavigateToScreen(@NonNull PreferenceScreen preferenceScreen) {
        boolean handled = false;
        if (getCallbackFragment() instanceof OnPreferenceStartScreenCallback) {
            handled = ((OnPreferenceStartScreenCallback) getCallbackFragment())
                    .onPreferenceStartScreen(this, preferenceScreen);
        }
        if (!handled && getActivity() instanceof OnPreferenceStartScreenCallback) {
            ((OnPreferenceStartScreenCallback) getActivity())
                    .onPreferenceStartScreen(this, preferenceScreen);
        }
    }

    /**
     * Finds a {@link Preference} based on its key.
     *
     * @param key The key of the preference to retrieve
     * @return The {@link Preference} with the key, or null
     * @see PreferenceGroup#findPreference(CharSequence)
     *
     * @deprecated Use {@link PreferenceFragmentCompat} instead
     */
    @Deprecated
    @Override
    @SuppressWarnings("TypeParameterUnusedInFormals")
    public <T extends Preference> T findPreference(@NonNull CharSequence key) {
        if (mPreferenceManager == null) {
            return null;
        }
        return mPreferenceManager.findPreference(key);
    }

    private void requirePreferenceManager() {
        if (mPreferenceManager == null) {
            throw new RuntimeException("This should be called after super.onCreate.");
        }
    }

    private void postBindPreferences() {
        if (mHandler.hasMessages(MSG_BIND_PREFERENCES)) return;
        mHandler.obtainMessage(MSG_BIND_PREFERENCES).sendToTarget();
    }

    void bindPreferences() {
        final PreferenceScreen preferenceScreen = getPreferenceScreen();
        if (preferenceScreen != null) {
            getListView().setAdapter(onCreateAdapter(preferenceScreen));
            preferenceScreen.onAttached();
        }
        onBindPreferences();
    }

    private void unbindPreferences() {
        final PreferenceScreen preferenceScreen = getPreferenceScreen();
        if (preferenceScreen != null) {
            preferenceScreen.onDetached();
        }
        onUnbindPreferences();
    }

    /** @hide */
    @RestrictTo(LIBRARY)
    protected void onBindPreferences() {}

    /** @hide */
    @RestrictTo(LIBRARY)
    protected void onUnbindPreferences() {}

    /**
     * @deprecated Use {@link PreferenceFragmentCompat} instead
     */
    @Deprecated
    public final RecyclerView getListView() {
        return mList;
    }

    /**
     * Creates the {@link RecyclerView} used to display the preferences. Subclasses may override
     * this to return a customized {@link RecyclerView}.
     *
     * @param inflater           The LayoutInflater object that can be used to inflate the
     *                           {@link RecyclerView}.
     * @param parent             The parent view that the RecyclerView will be attached to.
     *                           This method should not add the view itself, but this can be used
     *                           to generate the layout params of the view.
     * @param savedInstanceState If non-null, this view is being re-constructed from a previous
     *                           saved state as given here.
     * @return A new {@link RecyclerView} object to be placed into the view hierarchy
     *
     * @deprecated Use {@link PreferenceFragmentCompat} instead
     */
    @Deprecated
    @NonNull
    public RecyclerView onCreateRecyclerView(@NonNull LayoutInflater inflater,
            @NonNull ViewGroup parent, @Nullable Bundle savedInstanceState) {
        // If device detected is Auto, use Auto's custom layout that contains a custom ViewGroup
        // wrapping a RecyclerView
        if (mStyledContext.getPackageManager().hasSystemFeature(PackageManager
                .FEATURE_AUTOMOTIVE)) {
            RecyclerView recyclerView = parent.findViewById(R.id.recycler_view);
            if (recyclerView != null) {
                return recyclerView;
            }
        }
        RecyclerView recyclerView = (RecyclerView) inflater.inflate(
                R.layout.preference_recyclerview, parent, false);

        recyclerView.setLayoutManager(onCreateLayoutManager());
        recyclerView.setAccessibilityDelegateCompat(
                new PreferenceRecyclerViewAccessibilityDelegate(recyclerView));

        return recyclerView;
    }

    /**
     * Called from {@link #onCreateRecyclerView} to create the {@link RecyclerView.LayoutManager}
     * for the created {@link RecyclerView}.
     *
     * @return A new {@link RecyclerView.LayoutManager} instance
     *
     * @deprecated Use {@link PreferenceFragmentCompat} instead
     */
    @Deprecated
    @NonNull
    public RecyclerView.LayoutManager onCreateLayoutManager() {
        return new LinearLayoutManager(getActivity());
    }

    /**
     * Creates the root adapter.
     *
     * @param preferenceScreen The {@link PreferenceScreen} object to create the adapter for
     * @return An adapter that contains the preferences contained in this {@link PreferenceScreen}
     *
     * @deprecated Use {@link PreferenceFragmentCompat} instead
     */
    @Deprecated
    @NonNull
    protected RecyclerView.Adapter onCreateAdapter(@NonNull PreferenceScreen preferenceScreen) {
        return new PreferenceGroupAdapter(preferenceScreen);
    }

    /**
     * Called when a preference in the tree requests to display a dialog. Subclasses should
     * override this method to display custom dialogs or to handle dialogs for custom preference
     * classes.
     *
     * @param preference The {@link Preference} object requesting the dialog
     *
     * @deprecated Use {@link PreferenceFragmentCompat} instead
     */
    @Deprecated
    @Override
    public void onDisplayPreferenceDialog(@NonNull Preference preference) {

        boolean handled = false;
        if (getCallbackFragment() instanceof OnPreferenceDisplayDialogCallback) {
            handled = ((OnPreferenceDisplayDialogCallback) getCallbackFragment())
                    .onPreferenceDisplayDialog(this, preference);
        }
        if (!handled && getActivity() instanceof OnPreferenceDisplayDialogCallback) {
            handled = ((OnPreferenceDisplayDialogCallback) getActivity())
                    .onPreferenceDisplayDialog(this, preference);
        }

        if (handled) {
            return;
        }

        // check if dialog is already showing
        if (getFragmentManager().findFragmentByTag(DIALOG_FRAGMENT_TAG) != null) {
            return;
        }

        final android.app.DialogFragment f;
        if (preference instanceof EditTextPreference) {
            f = EditTextPreferenceDialogFragment.newInstance(preference.getKey());
        } else if (preference instanceof ListPreference) {
            f = ListPreferenceDialogFragment.newInstance(preference.getKey());
        } else if (preference instanceof MultiSelectListPreference) {
            f = MultiSelectListPreferenceDialogFragment.newInstance(preference.getKey());
        } else {
            throw new IllegalArgumentException("Tried to display dialog for unknown "
                    + "preference type. Did you forget to override onDisplayPreferenceDialog()?");
        }
        f.setTargetFragment(this, 0);
        f.show(getFragmentManager(), DIALOG_FRAGMENT_TAG);
    }

    /**
     * A wrapper for getParentFragment which is v17+. Used by the leanback preference library.
     *
     * @return The {@link android.app.Fragment} to possibly use as a callback
     * @hide
     */
    @RestrictTo(LIBRARY)
    public android.app.Fragment getCallbackFragment() {
        return null;
    }

    /**
     * @deprecated Use {@link PreferenceFragmentCompat} instead
     */
    @Deprecated
    public void scrollToPreference(@NonNull String key) {
        scrollToPreferenceInternal(null, key);
    }

    /**
     * @deprecated Use {@link PreferenceFragmentCompat} instead
     */
    @Deprecated
    public void scrollToPreference(@NonNull Preference preference) {
        scrollToPreferenceInternal(preference, null);
    }

    private void scrollToPreferenceInternal(final Preference preference, final String key) {
        final Runnable r = new Runnable() {
            @Override
            public void run() {
                final RecyclerView.Adapter<?> adapter = mList.getAdapter();
                if (!(adapter instanceof PreferenceGroup.PreferencePositionCallback)) {
                    if (adapter != null) {
                        throw new IllegalStateException("Adapter must implement "
                                + "PreferencePositionCallback");
                    } else {
                        // Adapter was set to null, so don't scroll
                        return;
                    }
                }
                final int position;
                if (preference != null) {
                    position = ((PreferenceGroup.PreferencePositionCallback) adapter)
                            .getPreferenceAdapterPosition(preference);
                } else {
                    position = ((PreferenceGroup.PreferencePositionCallback) adapter)
                            .getPreferenceAdapterPosition(key);
                }
                if (position != RecyclerView.NO_POSITION) {
                    mList.scrollToPosition(position);
                } else {
                    // Item not found, wait for an update and try again
                    adapter.registerAdapterDataObserver(
                            new ScrollToPreferenceObserver(adapter, mList, preference, key));
                }
            }
        };
        if (mList == null) {
            mSelectPreferenceRunnable = r;
        } else {
            r.run();
        }
    }

    /**
     * Interface that the fragment's containing activity should implement to be able to process
     * preference items that wish to switch to a specified fragment.
     */
    public interface OnPreferenceStartFragmentCallback {
        /**
         * Called when the user has clicked on a Preference that has a fragment class name
         * associated with it. The implementation should instantiate and switch to an instance
         * of the given fragment.
         *
         * @param caller The fragment requesting navigation
         * @param pref   The preference requesting the fragment
         * @return {@code true} if the fragment creation has been handled
         */
        boolean onPreferenceStartFragment(@NonNull PreferenceFragment caller,
                @NonNull Preference pref);
    }

    /**
     * Interface that the fragment's containing activity should implement to be able to process
     * preference items that wish to switch to a new screen of preferences.
     */
    public interface OnPreferenceStartScreenCallback {
        /**
         * Called when the user has clicked on a {@link PreferenceScreen} in order to navigate to
         * a new screen of preferences.
         *
         * @param caller The fragment requesting navigation
         * @param pref   The preference screen to navigate to
         * @return {@code true} if the screen navigation has been handled
         */
        boolean onPreferenceStartScreen(@NonNull PreferenceFragment caller,
                @NonNull PreferenceScreen pref);
    }

    /**
     * Interface that the fragment's containing activity should implement to be able to process
     * preference items that wish to display a dialog.
     */
    public interface OnPreferenceDisplayDialogCallback {
        /**
         * @param caller The fragment containing the preference requesting the dialog
         * @param pref   The preference requesting the dialog
         * @return {@code true} if the dialog creation has been handled
         */
        boolean onPreferenceDisplayDialog(@NonNull PreferenceFragment caller,
                @NonNull Preference pref);
    }

    private static class ScrollToPreferenceObserver extends RecyclerView.AdapterDataObserver {
        private final RecyclerView.Adapter<?> mAdapter;
        private final RecyclerView mList;
        private final Preference mPreference;
        private final String mKey;

        ScrollToPreferenceObserver(@NonNull RecyclerView.Adapter<?> adapter,
                @NonNull RecyclerView list, Preference preference, String key) {
            mAdapter = adapter;
            mList = list;
            mPreference = preference;
            mKey = key;
        }

        private void scrollToPreference() {
            mAdapter.unregisterAdapterDataObserver(this);
            final int position;
            if (mPreference != null) {
                position = ((PreferenceGroup.PreferencePositionCallback) mAdapter)
                        .getPreferenceAdapterPosition(mPreference);
            } else {
                position = ((PreferenceGroup.PreferencePositionCallback) mAdapter)
                        .getPreferenceAdapterPosition(mKey);
            }
            if (position != RecyclerView.NO_POSITION) {
                mList.scrollToPosition(position);
            }
        }

        @Override
        public void onChanged() {
            scrollToPreference();
        }

        @Override
        public void onItemRangeChanged(int positionStart, int itemCount) {
            scrollToPreference();
        }

        @Override
        public void onItemRangeChanged(int positionStart, int itemCount, Object payload) {
            scrollToPreference();
        }

        @Override
        public void onItemRangeInserted(int positionStart, int itemCount) {
            scrollToPreference();
        }

        @Override
        public void onItemRangeRemoved(int positionStart, int itemCount) {
            scrollToPreference();
        }

        @Override
        public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
            scrollToPreference();
        }
    }

    private class DividerDecoration extends RecyclerView.ItemDecoration {

        private Drawable mDivider;
        private int mDividerHeight;
        private boolean mAllowDividerAfterLastItem = true;

        DividerDecoration() {}

        @Override
        public void onDrawOver(@NonNull Canvas c, @NonNull RecyclerView parent,
                @NonNull RecyclerView.State state) {
            if (mDivider == null) {
                return;
            }
            final int childCount = parent.getChildCount();
            final int width = parent.getWidth();
            for (int childViewIndex = 0; childViewIndex < childCount; childViewIndex++) {
                final View view = parent.getChildAt(childViewIndex);
                if (shouldDrawDividerBelow(view, parent)) {
                    int top = (int) view.getY() + view.getHeight();
                    mDivider.setBounds(0, top, width, top + mDividerHeight);
                    mDivider.draw(c);
                }
            }
        }

        @Override
        public void getItemOffsets(@NonNull Rect outRect, @NonNull View view,
                @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
            if (shouldDrawDividerBelow(view, parent)) {
                outRect.bottom = mDividerHeight;
            }
        }

        private boolean shouldDrawDividerBelow(@NonNull View view, @NonNull RecyclerView parent) {
            final RecyclerView.ViewHolder holder = parent.getChildViewHolder(view);
            final boolean dividerAllowedBelow = holder instanceof PreferenceViewHolder
                    && ((PreferenceViewHolder) holder).isDividerAllowedBelow();
            if (!dividerAllowedBelow) {
                return false;
            }
            boolean nextAllowed = mAllowDividerAfterLastItem;
            int index = parent.indexOfChild(view);
            if (index < parent.getChildCount() - 1) {
                final View nextView = parent.getChildAt(index + 1);
                final RecyclerView.ViewHolder nextHolder = parent.getChildViewHolder(nextView);
                nextAllowed = nextHolder instanceof PreferenceViewHolder
                        && ((PreferenceViewHolder) nextHolder).isDividerAllowedAbove();
            }
            return nextAllowed;
        }

        public void setDivider(@Nullable Drawable divider) {
            if (divider != null) {
                mDividerHeight = divider.getIntrinsicHeight();
            } else {
                mDividerHeight = 0;
            }
            mDivider = divider;
            mList.invalidateItemDecorations();
        }

        public void setDividerHeight(int dividerHeight) {
            mDividerHeight = dividerHeight;
            mList.invalidateItemDecorations();
        }

        public void setAllowDividerAfterLastItem(boolean allowDividerAfterLastItem) {
            mAllowDividerAfterLastItem = allowDividerAfterLastItem;
        }
    }
}