Automatic sources dropoff on 2020-06-10 18:32:38.095721 The change is generated with prebuilt drop tool. Change-Id: I24cbf6ba6db262a1ae1445db1427a08fee35b3b4
diff --git a/android/preference/PreferenceFragment.java b/android/preference/PreferenceFragment.java new file mode 100644 index 0000000..3f6e505 --- /dev/null +++ b/android/preference/PreferenceFragment.java
@@ -0,0 +1,460 @@ +/* + * Copyright (C) 2010 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 android.preference; + +import android.annotation.Nullable; +import android.annotation.XmlRes; +import android.app.Activity; +import android.app.Fragment; +import android.compat.annotation.UnsupportedAppUsage; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.res.TypedArray; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.text.TextUtils; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnKeyListener; +import android.view.ViewGroup; +import android.widget.ListView; +import android.widget.TextView; + +/** + * Shows a hierarchy of {@link Preference} objects as + * lists. These preferences will + * automatically save to {@link SharedPreferences} as the user interacts with + * them. To retrieve an instance of {@link 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 showing these other screens from the preference hierarchy. + * <p> + * The preference hierarchy can be formed in multiple ways: + * <li> From an XML file specifying the hierarchy + * <li> From different {@link Activity Activities} that each specify its own + * preferences in an XML file via {@link Activity} meta-data + * <li> From an object hierarchy rooted with {@link PreferenceScreen} + * <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 {@link Intent} to query {@link Activity Activities} that each + * have preferences, use {@link #addPreferencesFromIntent}. Each + * {@link Activity} can specify meta-data in the manifest (via the key + * {@link PreferenceManager#METADATA_KEY_PREFERENCES}) that points to an XML + * resource. These XML resources will be inflated into a single preference + * hierarchy and shown by this fragment. + * <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(PreferenceScreen, Preference)}. + * + * <div class="special reference"> + * <h3>Developer Guides</h3> + * <p>For information about using {@code PreferenceFragment}, + * read the <a href="{@docRoot}guide/topics/ui/settings.html">Settings</a> + * guide.</p> + * </div> + * + * @see Preference + * @see PreferenceScreen + * + * @deprecated Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a> + * <a href="{@docRoot}reference/androidx/preference/package-summary.html"> + * Preference Library</a> for consistent behavior across all devices. For more information on + * using the AndroidX Preference Library see + * <a href="{@docRoot}guide/topics/ui/settings.html">Settings</a>. + */ +@Deprecated +public abstract class PreferenceFragment extends Fragment implements + PreferenceManager.OnPreferenceTreeClickListener { + + private static final String PREFERENCES_TAG = "android:preferences"; + + @UnsupportedAppUsage + private PreferenceManager mPreferenceManager; + private ListView mList; + private boolean mHavePrefs; + private boolean mInitDone; + + private int mLayoutResId = com.android.internal.R.layout.preference_list_fragment; + + /** + * The starting request code given out to preference framework. + */ + private static final int FIRST_REQUEST_CODE = 100; + + private static final int MSG_BIND_PREFERENCES = 1; + private Handler mHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + + case MSG_BIND_PREFERENCES: + bindPreferences(); + break; + } + } + }; + + final private Runnable mRequestFocus = new Runnable() { + public void run() { + mList.focusableViewAvailable(mList); + } + }; + + /** + * Interface that PreferenceFragment's containing activity should + * implement to be able to process preference items that wish to + * switch to a new fragment. + * + * @deprecated Use {@link + * android.support.v7.preference.PreferenceFragmentCompat.OnPreferenceStartFragmentCallback} + */ + @Deprecated + public interface OnPreferenceStartFragmentCallback { + /** + * Called when the user has clicked on a Preference that has + * a fragment class name associated with it. The implementation + * to should instantiate and switch to an instance of the given + * fragment. + */ + boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref); + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mPreferenceManager = new PreferenceManager(getActivity(), FIRST_REQUEST_CODE); + mPreferenceManager.setFragment(this); + } + + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, + @Nullable Bundle savedInstanceState) { + + TypedArray a = getActivity().obtainStyledAttributes(null, + com.android.internal.R.styleable.PreferenceFragment, + com.android.internal.R.attr.preferenceFragmentStyle, + 0); + + mLayoutResId = a.getResourceId(com.android.internal.R.styleable.PreferenceFragment_layout, + mLayoutResId); + + a.recycle(); + + return inflater.inflate(mLayoutResId, container, false); + } + + @Override + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + TypedArray a = getActivity().obtainStyledAttributes(null, + com.android.internal.R.styleable.PreferenceFragment, + com.android.internal.R.attr.preferenceFragmentStyle, + 0); + + ListView lv = (ListView) view.findViewById(android.R.id.list); + if (lv != null + && a.hasValueOrEmpty(com.android.internal.R.styleable.PreferenceFragment_divider)) { + lv.setDivider( + a.getDrawable(com.android.internal.R.styleable.PreferenceFragment_divider)); + } + + a.recycle(); + } + + @Override + public void onActivityCreated(@Nullable Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + if (mHavePrefs) { + bindPreferences(); + } + + mInitDone = true; + + if (savedInstanceState != null) { + Bundle container = savedInstanceState.getBundle(PREFERENCES_TAG); + if (container != null) { + final PreferenceScreen preferenceScreen = getPreferenceScreen(); + if (preferenceScreen != null) { + preferenceScreen.restoreHierarchyState(container); + } + } + } + } + + @Override + public void onStart() { + super.onStart(); + mPreferenceManager.setOnPreferenceTreeClickListener(this); + } + + @Override + public void onStop() { + super.onStop(); + mPreferenceManager.dispatchActivityStop(); + mPreferenceManager.setOnPreferenceTreeClickListener(null); + } + + @Override + public void onDestroyView() { + if (mList != null) { + mList.setOnKeyListener(null); + } + mList = null; + mHandler.removeCallbacks(mRequestFocus); + mHandler.removeMessages(MSG_BIND_PREFERENCES); + super.onDestroyView(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + mPreferenceManager.dispatchActivityDestroy(); + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + + final PreferenceScreen preferenceScreen = getPreferenceScreen(); + if (preferenceScreen != null) { + Bundle container = new Bundle(); + preferenceScreen.saveHierarchyState(container); + outState.putBundle(PREFERENCES_TAG, container); + } + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + + mPreferenceManager.dispatchActivityResult(requestCode, resultCode, data); + } + + /** + * Returns the {@link PreferenceManager} used by this fragment. + * @return The {@link PreferenceManager}. + */ + 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. + */ + 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. + */ + public PreferenceScreen getPreferenceScreen() { + return mPreferenceManager.getPreferenceScreen(); + } + + /** + * Adds preferences from activities that match the given {@link Intent}. + * + * @param intent The {@link Intent} to query activities. + */ + public void addPreferencesFromIntent(Intent intent) { + requirePreferenceManager(); + + setPreferenceScreen(mPreferenceManager.inflateFromIntent(intent, getPreferenceScreen())); + } + + /** + * Inflates the given XML resource and adds the preference hierarchy to the current + * preference hierarchy. + * + * @param preferencesResId The XML resource ID to inflate. + */ + public void addPreferencesFromResource(@XmlRes int preferencesResId) { + requirePreferenceManager(); + + setPreferenceScreen(mPreferenceManager.inflateFromResource(getActivity(), + preferencesResId, getPreferenceScreen())); + } + + /** + * {@inheritDoc} + */ + public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, + Preference preference) { + if (preference.getFragment() != null && + getActivity() instanceof OnPreferenceStartFragmentCallback) { + return ((OnPreferenceStartFragmentCallback)getActivity()).onPreferenceStartFragment( + this, preference); + } + return false; + } + + /** + * 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) + */ + public Preference findPreference(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(); + } + + private void bindPreferences() { + final PreferenceScreen preferenceScreen = getPreferenceScreen(); + if (preferenceScreen != null) { + View root = getView(); + if (root != null) { + View titleView = root.findViewById(android.R.id.title); + if (titleView instanceof TextView) { + CharSequence title = preferenceScreen.getTitle(); + if (TextUtils.isEmpty(title)) { + titleView.setVisibility(View.GONE); + } else { + ((TextView) titleView).setText(title); + titleView.setVisibility(View.VISIBLE); + } + } + } + + preferenceScreen.bind(getListView()); + } + onBindPreferences(); + } + + /** @hide */ + protected void onBindPreferences() { + } + + /** @hide */ + protected void onUnbindPreferences() { + } + + /** @hide */ + @UnsupportedAppUsage + public ListView getListView() { + ensureList(); + return mList; + } + + /** @hide */ + public boolean hasListView() { + if (mList != null) { + return true; + } + View root = getView(); + if (root == null) { + return false; + } + View rawListView = root.findViewById(android.R.id.list); + if (!(rawListView instanceof ListView)) { + return false; + } + mList = (ListView)rawListView; + if (mList == null) { + return false; + } + return true; + } + + private void ensureList() { + if (mList != null) { + return; + } + View root = getView(); + if (root == null) { + throw new IllegalStateException("Content view not yet created"); + } + View rawListView = root.findViewById(android.R.id.list); + if (!(rawListView instanceof ListView)) { + throw new RuntimeException( + "Content has view with id attribute 'android.R.id.list' " + + "that is not a ListView class"); + } + mList = (ListView)rawListView; + if (mList == null) { + throw new RuntimeException( + "Your content must have a ListView whose id attribute is " + + "'android.R.id.list'"); + } + mList.setOnKeyListener(mListOnKeyListener); + mHandler.post(mRequestFocus); + } + + private OnKeyListener mListOnKeyListener = new OnKeyListener() { + + @Override + public boolean onKey(View v, int keyCode, KeyEvent event) { + Object selectedItem = mList.getSelectedItem(); + if (selectedItem instanceof Preference) { + View selectedView = mList.getSelectedView(); + return ((Preference)selectedItem).onKey( + selectedView, keyCode, event); + } + return false; + } + + }; +}