/* * 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 android.support.v7.preference; import android.content.Context; import android.content.res.TypedArray; import android.os.Bundle; import android.support.v4.content.res.TypedArrayUtils; import android.text.TextUtils; import android.util.AttributeSet; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * A container for multiple * {@link Preference} objects. It is a base class for Preference objects that are * parents, such as {@link PreferenceCategory} and {@link PreferenceScreen}. * *
For information about building a settings UI with Preferences, * read the Settings * guide.
*
* If this is called after preferences are added, they will not be
* re-ordered in the order they were added, hence call this method early on.
*
* @param orderingAsAdded Whether to order according to the order added.
* @see Preference#setOrder(int)
*/
public void setOrderingAsAdded(boolean orderingAsAdded) {
mOrderingAsAdded = orderingAsAdded;
}
/**
* Whether this group is ordering preferences in the order they are added.
*
* @return Whether this group orders based on the order the children are added.
* @see #setOrderingAsAdded(boolean)
*/
public boolean isOrderingAsAdded() {
return mOrderingAsAdded;
}
/**
* Called by the inflater to add an item to this group.
*/
public void addItemFromInflater(Preference preference) {
addPreference(preference);
}
/**
* Returns the number of children {@link Preference}s.
* @return The number of preference children in this group.
*/
public int getPreferenceCount() {
return mPreferenceList.size();
}
/**
* Returns the {@link Preference} at a particular index.
*
* @param index The index of the {@link Preference} to retrieve.
* @return The {@link Preference}.
*/
public Preference getPreference(int index) {
return mPreferenceList.get(index);
}
/**
* Adds a {@link Preference} at the correct position based on the
* preference's order.
*
* @param preference The preference to add.
* @return Whether the preference is now in this group.
*/
public boolean addPreference(Preference preference) {
if (mPreferenceList.contains(preference)) {
// Exists
return true;
}
if (preference.getOrder() == DEFAULT_ORDER) {
if (mOrderingAsAdded) {
preference.setOrder(mCurrentPreferenceOrder++);
}
if (preference instanceof PreferenceGroup) {
// TODO: fix (method is called tail recursively when inflating,
// so we won't end up properly passing this flag down to children
((PreferenceGroup)preference).setOrderingAsAdded(mOrderingAsAdded);
}
}
int insertionIndex = Collections.binarySearch(mPreferenceList, preference);
if (insertionIndex < 0) {
insertionIndex = insertionIndex * -1 - 1;
}
if (!onPrepareAddPreference(preference)) {
return false;
}
synchronized(this) {
mPreferenceList.add(insertionIndex, preference);
}
preference.onAttachedToHierarchy(getPreferenceManager());
if (mAttachedToHierarchy) {
preference.onAttached();
}
notifyHierarchyChanged();
return true;
}
/**
* Removes a {@link Preference} from this group.
*
* @param preference The preference to remove.
* @return Whether the preference was found and removed.
*/
public boolean removePreference(Preference preference) {
final boolean returnValue = removePreferenceInt(preference);
notifyHierarchyChanged();
return returnValue;
}
private boolean removePreferenceInt(Preference preference) {
synchronized(this) {
preference.onPrepareForRemoval();
return mPreferenceList.remove(preference);
}
}
/**
* Removes all {@link Preference Preferences} from this group.
*/
public void removeAll() {
synchronized(this) {
List
* This will recursively search for the preference into children that are
* also {@link PreferenceGroup PreferenceGroups}.
*
* @param key The key of the preference to retrieve.
* @return The {@link Preference} with the key, or null.
*/
public Preference findPreference(CharSequence key) {
if (TextUtils.equals(getKey(), key)) {
return this;
}
final int preferenceCount = getPreferenceCount();
for (int i = 0; i < preferenceCount; i++) {
final Preference preference = getPreference(i);
final String curKey = preference.getKey();
if (curKey != null && curKey.equals(key)) {
return preference;
}
if (preference instanceof PreferenceGroup) {
final Preference returnedPreference = ((PreferenceGroup)preference)
.findPreference(key);
if (returnedPreference != null) {
return returnedPreference;
}
}
}
return null;
}
/**
* Whether this preference group should be shown on the same screen as its
* contained preferences.
*
* @return True if the contained preferences should be shown on the same
* screen as this preference.
*/
protected boolean isOnSameScreenAsChildren() {
return true;
}
@Override
public void onAttached() {
super.onAttached();
// Mark as attached so if a preference is later added to this group, we
// can tell it we are already attached
mAttachedToHierarchy = true;
// Dispatch to all contained preferences
final int preferenceCount = getPreferenceCount();
for (int i = 0; i < preferenceCount; i++) {
getPreference(i).onAttached();
}
}
@Override
protected void onPrepareForRemoval() {
super.onPrepareForRemoval();
// We won't be attached to the activity anymore
mAttachedToHierarchy = false;
}
@Override
public void notifyDependencyChange(boolean disableDependents) {
super.notifyDependencyChange(disableDependents);
// Child preferences have an implicit dependency on their containing
// group. Dispatch dependency change to all contained preferences.
final int preferenceCount = getPreferenceCount();
for (int i = 0; i < preferenceCount; i++) {
getPreference(i).onParentChanged(this, disableDependents);
}
}
void sortPreferences() {
synchronized (this) {
Collections.sort(mPreferenceList);
}
}
@Override
protected void dispatchSaveInstanceState(Bundle container) {
super.dispatchSaveInstanceState(container);
// Dispatch to all contained preferences
final int preferenceCount = getPreferenceCount();
for (int i = 0; i < preferenceCount; i++) {
getPreference(i).dispatchSaveInstanceState(container);
}
}
@Override
protected void dispatchRestoreInstanceState(Bundle container) {
super.dispatchRestoreInstanceState(container);
// Dispatch to all contained preferences
final int preferenceCount = getPreferenceCount();
for (int i = 0; i < preferenceCount; i++) {
getPreference(i).dispatchRestoreInstanceState(container);
}
}
}