java.lang.Object
↳android.app.Fragment
↳androidx.preference.PreferenceFragment
Subclasses:
BaseLeanbackPreferenceFragment, LeanbackPreferenceFragment
Gradle dependencies
compile group: 'androidx.preference', name: 'preference', version: '1.2.1'
- groupId: androidx.preference
- artifactId: preference
- version: 1.2.1
Artifact androidx.preference:preference:1.2.1 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
Methods |
---|
public void | addPreferencesFromResource(int preferencesResId)
Inflates the given XML resource and adds the preference hierarchy to the current
preference hierarchy. |
public Preference | findPreference(java.lang.CharSequence key)
Finds a Preference based on its key. |
public android.app.Fragment | getCallbackFragment()
A wrapper for getParentFragment which is v17+. |
public final RecyclerView | getListView()
|
public PreferenceManager | getPreferenceManager()
Returns the PreferenceManager used by this fragment. |
public PreferenceScreen | getPreferenceScreen()
Gets the root of the preference hierarchy that this fragment is showing. |
protected void | onBindPreferences()
|
public void | onCreate(Bundle savedInstanceState)
|
protected RecyclerView.Adapter | onCreateAdapter(PreferenceScreen preferenceScreen)
Creates the root adapter. |
public RecyclerView.LayoutManager | onCreateLayoutManager()
Called from PreferenceFragment.onCreateRecyclerView(LayoutInflater, ViewGroup, Bundle) to create the
for the created RecyclerView. |
public abstract void | onCreatePreferences(Bundle savedInstanceState, java.lang.String rootKey)
Called during PreferenceFragment.onCreate(Bundle) to supply the preferences for this fragment. |
public RecyclerView | onCreateRecyclerView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState)
Creates the RecyclerView used to display the preferences. |
public View | onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
|
public void | onDestroyView()
|
public void | onDisplayPreferenceDialog(Preference preference)
Called when a preference in the tree requests to display a dialog. |
public void | onNavigateToScreen(PreferenceScreen preferenceScreen)
Called by PreferenceScreen.onClick() in order to navigate to a new screen of
preferences. |
public boolean | onPreferenceTreeClick(Preference preference)
|
public void | onSaveInstanceState(Bundle outState)
|
public void | onStart()
|
public void | onStop()
|
protected void | onUnbindPreferences()
|
public void | onViewCreated(View view, Bundle savedInstanceState)
|
public void | scrollToPreference(Preference preference)
|
public void | scrollToPreference(java.lang.String key)
|
public void | setDivider(Drawable divider)
Sets the Drawable that will be drawn between each item in the list. |
public void | setDividerHeight(int height)
Sets the height of the divider that will be drawn between each item in the list. |
public void | setPreferenceScreen(PreferenceScreen preferenceScreen)
Sets the root of the preference hierarchy that this fragment is showing. |
public void | setPreferencesFromResource(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.Object | clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Fields
public static final java.lang.String
ARG_PREFERENCE_ROOTDeprecated: 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
onDestroyView()
public void
onSaveInstanceState(Bundle outState)
Deprecated: Use PreferenceFragmentCompat instead
Returns the PreferenceManager used by this fragment.
Returns:
The PreferenceManager used by this fragment
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
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
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()
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
Deprecated: Use PreferenceFragmentCompat instead
Called from PreferenceFragment.onCreateRecyclerView(LayoutInflater, ViewGroup, Bundle) to create the
for the created RecyclerView.
Returns:
A new instance
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;
}
}
}