PreferenceGroup.java revision 66222008cbda61251014caf1442930a48561d25c
16904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler/* 26904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * Copyright (C) 2015 The Android Open Source Project 36904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * 46904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * Licensed under the Apache License, Version 2.0 (the "License"); 56904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * you may not use this file except in compliance with the License. 66904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * You may obtain a copy of the License at 76904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * 86904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * http://www.apache.org/licenses/LICENSE-2.0 96904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * 106904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * Unless required by applicable law or agreed to in writing, software 116904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * distributed under the License is distributed on an "AS IS" BASIS, 126904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * See the License for the specific language governing permissions and 146904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * limitations under the License 156904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler */ 166904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 176904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerpackage android.support.v7.preference; 186904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 196904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.content.Context; 206904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.content.res.TypedArray; 216904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.os.Bundle; 22c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantlerimport android.os.Handler; 2384765eaea7da18d0576db557959129e9d0db8e8cTony Mantlerimport android.support.v4.content.res.TypedArrayUtils; 24c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantlerimport android.support.v4.util.SimpleArrayMap; 256904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.text.TextUtils; 266904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.util.AttributeSet; 276904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 286904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport java.util.ArrayList; 296904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport java.util.Collections; 306904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport java.util.List; 316904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 326904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler/** 336904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * A container for multiple 346904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * {@link Preference} objects. It is a base class for Preference objects that are 356904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * parents, such as {@link PreferenceCategory} and {@link PreferenceScreen}. 366904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * 376904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * <div class="special reference"> 386904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * <h3>Developer Guides</h3> 396904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * <p>For information about building a settings UI with Preferences, 406904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * read the <a href="{@docRoot}guide/topics/ui/settings.html">Settings</a> 416904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * guide.</p> 426904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * </div> 436904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * 446904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * @attr ref android.R.styleable#PreferenceGroup_orderingFromXml 456904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler */ 466904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerpublic abstract class PreferenceGroup extends Preference { 476904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler /** 486904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * The container for child {@link Preference}s. This is sorted based on the 496904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * ordering, please use {@link #addPreference(Preference)} instead of adding 506904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * to this directly. 516904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler */ 526904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler private List<Preference> mPreferenceList; 536904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 546904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler private boolean mOrderingAsAdded = true; 556904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 566904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler private int mCurrentPreferenceOrder = 0; 576904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 58e61b4475e1837034d8926593aff9d35f8dfaebe2Tony Mantler private boolean mAttachedToHierarchy = false; 596904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 60c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler private final SimpleArrayMap<String, Long> mIdRecycleCache = new SimpleArrayMap<>(); 61c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler private final Handler mHandler = new Handler(); 62c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler private final Runnable mClearRecycleCacheRunnable = new Runnable() { 63c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler @Override 64c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler public void run() { 65c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler synchronized (this) { 66c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler mIdRecycleCache.clear(); 67c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler } 68c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler } 69c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler }; 70c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler 716904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler public PreferenceGroup(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 726904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler super(context, attrs, defStyleAttr, defStyleRes); 736904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 746904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler mPreferenceList = new ArrayList<>(); 756904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 766904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler final TypedArray a = context.obtainStyledAttributes( 776904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler attrs, R.styleable.PreferenceGroup, defStyleAttr, defStyleRes); 7884765eaea7da18d0576db557959129e9d0db8e8cTony Mantler 7984765eaea7da18d0576db557959129e9d0db8e8cTony Mantler mOrderingAsAdded = 8084765eaea7da18d0576db557959129e9d0db8e8cTony Mantler TypedArrayUtils.getBoolean(a, R.styleable.PreferenceGroup_orderingFromXml, 8184765eaea7da18d0576db557959129e9d0db8e8cTony Mantler R.styleable.PreferenceGroup_orderingFromXml, true); 8284765eaea7da18d0576db557959129e9d0db8e8cTony Mantler 836904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler a.recycle(); 846904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 856904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 866904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler public PreferenceGroup(Context context, AttributeSet attrs, int defStyleAttr) { 876904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler this(context, attrs, defStyleAttr, 0); 886904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 896904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 906904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler public PreferenceGroup(Context context, AttributeSet attrs) { 916904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler this(context, attrs, 0); 926904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 936904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 946904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler /** 956904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * Whether to order the {@link Preference} children of this group as they 966904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * are added. If this is false, the ordering will follow each Preference 976904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * order and default to alphabetic for those without an order. 986904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * <p> 996904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * If this is called after preferences are added, they will not be 1006904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * re-ordered in the order they were added, hence call this method early on. 1016904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * 1026904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * @param orderingAsAdded Whether to order according to the order added. 1036904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * @see Preference#setOrder(int) 1046904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler */ 1056904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler public void setOrderingAsAdded(boolean orderingAsAdded) { 1066904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler mOrderingAsAdded = orderingAsAdded; 1076904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 1086904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 1096904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler /** 1106904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * Whether this group is ordering preferences in the order they are added. 1116904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * 1126904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * @return Whether this group orders based on the order the children are added. 1136904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * @see #setOrderingAsAdded(boolean) 1146904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler */ 1156904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler public boolean isOrderingAsAdded() { 1166904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler return mOrderingAsAdded; 1176904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 1186904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 1196904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler /** 1206904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * Called by the inflater to add an item to this group. 1216904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler */ 1226904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler public void addItemFromInflater(Preference preference) { 1236904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler addPreference(preference); 1246904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 1256904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 1266904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler /** 1276904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * Returns the number of children {@link Preference}s. 1286904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * @return The number of preference children in this group. 1296904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler */ 1306904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler public int getPreferenceCount() { 1316904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler return mPreferenceList.size(); 1326904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 1336904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 1346904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler /** 1356904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * Returns the {@link Preference} at a particular index. 1366904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * 1376904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * @param index The index of the {@link Preference} to retrieve. 1386904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * @return The {@link Preference}. 1396904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler */ 1406904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler public Preference getPreference(int index) { 1416904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler return mPreferenceList.get(index); 1426904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 1436904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 1446904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler /** 1456904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * Adds a {@link Preference} at the correct position based on the 1466904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * preference's order. 1476904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * 1486904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * @param preference The preference to add. 1496904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * @return Whether the preference is now in this group. 1506904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler */ 1516904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler public boolean addPreference(Preference preference) { 1526904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler if (mPreferenceList.contains(preference)) { 1536904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler // Exists 1546904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler return true; 1556904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 1566904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 1576904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler if (preference.getOrder() == DEFAULT_ORDER) { 1586904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler if (mOrderingAsAdded) { 1596904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler preference.setOrder(mCurrentPreferenceOrder++); 1606904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 1616904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 1626904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler if (preference instanceof PreferenceGroup) { 1636904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler // TODO: fix (method is called tail recursively when inflating, 1646904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler // so we won't end up properly passing this flag down to children 1656904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler ((PreferenceGroup)preference).setOrderingAsAdded(mOrderingAsAdded); 1666904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 1676904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 1686904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 1696904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler int insertionIndex = Collections.binarySearch(mPreferenceList, preference); 1706904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler if (insertionIndex < 0) { 1716904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler insertionIndex = insertionIndex * -1 - 1; 1726904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 1736904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 1746904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler if (!onPrepareAddPreference(preference)) { 1756904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler return false; 1766904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 1776904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 1786904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler synchronized(this) { 1796904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler mPreferenceList.add(insertionIndex, preference); 1806904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 1816904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 182c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler final PreferenceManager preferenceManager = getPreferenceManager(); 183c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler final String key = preference.getKey(); 184c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler final long id; 185c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler if (key != null && mIdRecycleCache.containsKey(key)) { 186c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler id = mIdRecycleCache.get(key); 187c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler mIdRecycleCache.remove(key); 188c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler } else { 189c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler id = preferenceManager.getNextId(); 190c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler } 191c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler preference.onAttachedToHierarchy(preferenceManager, id); 1926904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 193e61b4475e1837034d8926593aff9d35f8dfaebe2Tony Mantler if (mAttachedToHierarchy) { 1946904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler preference.onAttached(); 1956904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 1966904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 1976904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler notifyHierarchyChanged(); 1986904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 1996904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler return true; 2006904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 2016904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 2026904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler /** 2036904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * Removes a {@link Preference} from this group. 2046904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * 2056904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * @param preference The preference to remove. 2066904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * @return Whether the preference was found and removed. 2076904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler */ 2086904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler public boolean removePreference(Preference preference) { 2096904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler final boolean returnValue = removePreferenceInt(preference); 2106904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler notifyHierarchyChanged(); 2116904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler return returnValue; 2126904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 2136904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 2146904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler private boolean removePreferenceInt(Preference preference) { 2156904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler synchronized(this) { 2166904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler preference.onPrepareForRemoval(); 2178f7f0d48fac8f83e90a04ba67f9a03f93c6ed262Jason Monk boolean success = mPreferenceList.remove(preference); 218c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler if (success) { 219c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler // If this preference, or another preference with the same key, gets re-added 220c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler // immediately, we want it to have the same id so that it can be correctly tracked 221c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler // in the adapter by RecyclerView, to make it appear as if it has only been 222c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler // seamlessly updated. If the preference is not re-added by the time the handler 223c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler // runs, we take that as a signal that the preference will not be re-added soon 224c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler // in which case it does not need to retain the same id. 225c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler 226c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler // If two (or more) preferences have the same (or null) key and both are removed 227c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler // and then re-added, only one id will be recycled and the second (and later) 228c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler // preferences will receive a newly generated id. This use pattern of the preference 229c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler // API is strongly discouraged. 230c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler final String key = preference.getKey(); 231c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler if (key != null) { 232c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler mIdRecycleCache.put(key, preference.getId()); 233c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler mHandler.removeCallbacks(mClearRecycleCacheRunnable); 234c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler mHandler.post(mClearRecycleCacheRunnable); 235c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler } 236c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler if (mAttachedToHierarchy) { 237c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler preference.onDetached(); 238c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler } 2398f7f0d48fac8f83e90a04ba67f9a03f93c6ed262Jason Monk } 240c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler 2418f7f0d48fac8f83e90a04ba67f9a03f93c6ed262Jason Monk return success; 2426904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 2436904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 2446904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 2456904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler /** 2466904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * Removes all {@link Preference Preferences} from this group. 2476904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler */ 2486904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler public void removeAll() { 2496904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler synchronized(this) { 2506904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler List<Preference> preferenceList = mPreferenceList; 2516904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler for (int i = preferenceList.size() - 1; i >= 0; i--) { 2526904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler removePreferenceInt(preferenceList.get(0)); 2536904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 2546904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 2556904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler notifyHierarchyChanged(); 2566904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 2576904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 2586904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler /** 2596904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * Prepares a {@link Preference} to be added to the group. 2606904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * 2616904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * @param preference The preference to add. 2626904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * @return Whether to allow adding the preference (true), or not (false). 2636904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler */ 2646904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler protected boolean onPrepareAddPreference(Preference preference) { 2656904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler preference.onParentChanged(this, shouldDisableDependents()); 2666904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler return true; 2676904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 2686904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 2696904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler /** 2706904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * Finds a {@link Preference} based on its key. If two {@link Preference} 2716904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * share the same key (not recommended), the first to appear will be 2726904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * returned (to retrieve the other preference with the same key, call this 2736904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * method on the first preference). If this preference has the key, it will 2746904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * not be returned. 2756904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * <p> 2766904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * This will recursively search for the preference into children that are 2776904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * also {@link PreferenceGroup PreferenceGroups}. 2786904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * 2796904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * @param key The key of the preference to retrieve. 2806904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * @return The {@link Preference} with the key, or null. 2816904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler */ 2826904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler public Preference findPreference(CharSequence key) { 2836904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler if (TextUtils.equals(getKey(), key)) { 2846904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler return this; 2856904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 2866904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler final int preferenceCount = getPreferenceCount(); 2876904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler for (int i = 0; i < preferenceCount; i++) { 2886904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler final Preference preference = getPreference(i); 2896904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler final String curKey = preference.getKey(); 2906904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 2916904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler if (curKey != null && curKey.equals(key)) { 2926904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler return preference; 2936904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 2946904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 2956904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler if (preference instanceof PreferenceGroup) { 2966904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler final Preference returnedPreference = ((PreferenceGroup)preference) 2976904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler .findPreference(key); 2986904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler if (returnedPreference != null) { 2996904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler return returnedPreference; 3006904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 3016904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 3026904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 3036904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 3046904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler return null; 3056904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 3066904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 3076904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler /** 3086904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * Whether this preference group should be shown on the same screen as its 3096904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * contained preferences. 3106904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * 3116904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * @return True if the contained preferences should be shown on the same 3126904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * screen as this preference. 3136904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler */ 3146904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler protected boolean isOnSameScreenAsChildren() { 3156904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler return true; 3166904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 3176904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 31883deca7547a76f037c32fdc946173b4708b8d05bTony Mantler /** 31983deca7547a76f037c32fdc946173b4708b8d05bTony Mantler * Returns true if we're between {@link #onAttached()} and {@link #onPrepareForRemoval()} 32083deca7547a76f037c32fdc946173b4708b8d05bTony Mantler * @hide 32183deca7547a76f037c32fdc946173b4708b8d05bTony Mantler */ 32283deca7547a76f037c32fdc946173b4708b8d05bTony Mantler public boolean isAttached() { 32383deca7547a76f037c32fdc946173b4708b8d05bTony Mantler return mAttachedToHierarchy; 32483deca7547a76f037c32fdc946173b4708b8d05bTony Mantler } 32583deca7547a76f037c32fdc946173b4708b8d05bTony Mantler 3266904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler @Override 327e61b4475e1837034d8926593aff9d35f8dfaebe2Tony Mantler public void onAttached() { 3286904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler super.onAttached(); 3296904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 3306904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler // Mark as attached so if a preference is later added to this group, we 3316904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler // can tell it we are already attached 332e61b4475e1837034d8926593aff9d35f8dfaebe2Tony Mantler mAttachedToHierarchy = true; 3336904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 3346904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler // Dispatch to all contained preferences 3356904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler final int preferenceCount = getPreferenceCount(); 3366904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler for (int i = 0; i < preferenceCount; i++) { 3376904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler getPreference(i).onAttached(); 3386904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 3396904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 3406904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 3416904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler @Override 3428f7f0d48fac8f83e90a04ba67f9a03f93c6ed262Jason Monk public void onDetached() { 3438f7f0d48fac8f83e90a04ba67f9a03f93c6ed262Jason Monk super.onDetached(); 3446904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 3456904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler // We won't be attached to the activity anymore 346e61b4475e1837034d8926593aff9d35f8dfaebe2Tony Mantler mAttachedToHierarchy = false; 3478f7f0d48fac8f83e90a04ba67f9a03f93c6ed262Jason Monk 3488f7f0d48fac8f83e90a04ba67f9a03f93c6ed262Jason Monk // Dispatch to all contained preferences 3498f7f0d48fac8f83e90a04ba67f9a03f93c6ed262Jason Monk final int preferenceCount = getPreferenceCount(); 3508f7f0d48fac8f83e90a04ba67f9a03f93c6ed262Jason Monk for (int i = 0; i < preferenceCount; i++) { 3518f7f0d48fac8f83e90a04ba67f9a03f93c6ed262Jason Monk getPreference(i).onDetached(); 3528f7f0d48fac8f83e90a04ba67f9a03f93c6ed262Jason Monk } 3536904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 3546904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 3556904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler @Override 3566904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler public void notifyDependencyChange(boolean disableDependents) { 3576904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler super.notifyDependencyChange(disableDependents); 3586904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 3596904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler // Child preferences have an implicit dependency on their containing 3606904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler // group. Dispatch dependency change to all contained preferences. 3616904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler final int preferenceCount = getPreferenceCount(); 3626904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler for (int i = 0; i < preferenceCount; i++) { 3636904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler getPreference(i).onParentChanged(this, disableDependents); 3646904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 3656904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 3666904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 3676904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler void sortPreferences() { 3686904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler synchronized (this) { 3696904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler Collections.sort(mPreferenceList); 3706904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 3716904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 3726904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 3736904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler @Override 3746904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler protected void dispatchSaveInstanceState(Bundle container) { 3756904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler super.dispatchSaveInstanceState(container); 3766904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 3776904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler // Dispatch to all contained preferences 3786904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler final int preferenceCount = getPreferenceCount(); 3796904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler for (int i = 0; i < preferenceCount; i++) { 3806904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler getPreference(i).dispatchSaveInstanceState(container); 3816904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 3826904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 3836904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 3846904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler @Override 3856904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler protected void dispatchRestoreInstanceState(Bundle container) { 3866904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler super.dispatchRestoreInstanceState(container); 3876904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 3886904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler // Dispatch to all contained preferences 3896904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler final int preferenceCount = getPreferenceCount(); 3906904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler for (int i = 0; i < preferenceCount; i++) { 3916904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler getPreference(i).dispatchRestoreInstanceState(container); 3926904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 3936904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 3946904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 39566222008cbda61251014caf1442930a48561d25cTony Mantler /** 39666222008cbda61251014caf1442930a48561d25cTony Mantler * Interface for PreferenceGroup Adapters to implement so that 39766222008cbda61251014caf1442930a48561d25cTony Mantler * {@link android.support.v14.preference.PreferenceFragment#scrollToPreference(String)} and 39866222008cbda61251014caf1442930a48561d25cTony Mantler * {@link android.support.v14.preference.PreferenceFragment#scrollToPreference(Preference)} or 39966222008cbda61251014caf1442930a48561d25cTony Mantler * {@link PreferenceFragmentCompat#scrollToPreference(String)} and 40066222008cbda61251014caf1442930a48561d25cTony Mantler * {@link PreferenceFragmentCompat#scrollToPreference(Preference)} 40166222008cbda61251014caf1442930a48561d25cTony Mantler * can determine the correct scroll position to request. 40266222008cbda61251014caf1442930a48561d25cTony Mantler */ 40366222008cbda61251014caf1442930a48561d25cTony Mantler public interface PreferencePositionCallback { 40466222008cbda61251014caf1442930a48561d25cTony Mantler 40566222008cbda61251014caf1442930a48561d25cTony Mantler /** 40666222008cbda61251014caf1442930a48561d25cTony Mantler * Return the adapter position of the first {@link Preference} with the specified key 40766222008cbda61251014caf1442930a48561d25cTony Mantler * @param key Key of {@link Preference} to find 40866222008cbda61251014caf1442930a48561d25cTony Mantler * @return Adapter position of the {@link Preference} or 40966222008cbda61251014caf1442930a48561d25cTony Mantler * {@link android.support.v7.widget.RecyclerView#NO_POSITION} if not found 41066222008cbda61251014caf1442930a48561d25cTony Mantler */ 41166222008cbda61251014caf1442930a48561d25cTony Mantler int getPreferenceAdapterPosition(String key); 41266222008cbda61251014caf1442930a48561d25cTony Mantler 41366222008cbda61251014caf1442930a48561d25cTony Mantler /** 41466222008cbda61251014caf1442930a48561d25cTony Mantler * Return the adapter position of the specified {@link Preference} object 41566222008cbda61251014caf1442930a48561d25cTony Mantler * @param preference {@link Preference} object to find 41666222008cbda61251014caf1442930a48561d25cTony Mantler * @return Adapter position of the {@link Preference} or 41766222008cbda61251014caf1442930a48561d25cTony Mantler * {@link android.support.v7.widget.RecyclerView#NO_POSITION} if not found 41866222008cbda61251014caf1442930a48561d25cTony Mantler */ 41966222008cbda61251014caf1442930a48561d25cTony Mantler int getPreferenceAdapterPosition(Preference preference); 42066222008cbda61251014caf1442930a48561d25cTony Mantler } 4216904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler} 422