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 198e10080c914d1ad0784394fa3026b85535535847Aurimas Liutikasimport static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP; 208e10080c914d1ad0784394fa3026b85535535847Aurimas Liutikas 216904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.content.Context; 226904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.content.res.TypedArray; 236904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.os.Bundle; 24c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantlerimport android.os.Handler; 25c39d9c75590eca86a5e7e32a8824ba04a0d42e9bAlan Viveretteimport android.support.annotation.RestrictTo; 2684765eaea7da18d0576db557959129e9d0db8e8cTony Mantlerimport android.support.v4.content.res.TypedArrayUtils; 27c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantlerimport android.support.v4.util.SimpleArrayMap; 286904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.text.TextUtils; 296904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport android.util.AttributeSet; 306904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 316904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport java.util.ArrayList; 326904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport java.util.Collections; 336904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerimport java.util.List; 346904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 356904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler/** 366904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * A container for multiple 376904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * {@link Preference} objects. It is a base class for Preference objects that are 386904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * parents, such as {@link PreferenceCategory} and {@link PreferenceScreen}. 396904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * 406904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * <div class="special reference"> 416904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * <h3>Developer Guides</h3> 426904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * <p>For information about building a settings UI with Preferences, 436904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * read the <a href="{@docRoot}guide/topics/ui/settings.html">Settings</a> 446904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * guide.</p> 456904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * </div> 466904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * 47929f27aab7ac7231f3734c988d5ee7201627d535Alan Viverette * @attr name android:orderingFromXml 486904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler */ 496904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantlerpublic abstract class PreferenceGroup extends Preference { 506904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler /** 516904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * The container for child {@link Preference}s. This is sorted based on the 526904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * ordering, please use {@link #addPreference(Preference)} instead of adding 536904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * to this directly. 546904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler */ 556904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler private List<Preference> mPreferenceList; 566904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 576904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler private boolean mOrderingAsAdded = true; 586904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 596904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler private int mCurrentPreferenceOrder = 0; 606904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 61e61b4475e1837034d8926593aff9d35f8dfaebe2Tony Mantler private boolean mAttachedToHierarchy = false; 626904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 63c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler private final SimpleArrayMap<String, Long> mIdRecycleCache = new SimpleArrayMap<>(); 64c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler private final Handler mHandler = new Handler(); 65c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler private final Runnable mClearRecycleCacheRunnable = new Runnable() { 66c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler @Override 67c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler public void run() { 68c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler synchronized (this) { 69c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler mIdRecycleCache.clear(); 70c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler } 71c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler } 72c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler }; 73c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler 746904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler public PreferenceGroup(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 756904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler super(context, attrs, defStyleAttr, defStyleRes); 766904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 776904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler mPreferenceList = new ArrayList<>(); 786904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 796904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler final TypedArray a = context.obtainStyledAttributes( 806904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler attrs, R.styleable.PreferenceGroup, defStyleAttr, defStyleRes); 8184765eaea7da18d0576db557959129e9d0db8e8cTony Mantler 8284765eaea7da18d0576db557959129e9d0db8e8cTony Mantler mOrderingAsAdded = 8384765eaea7da18d0576db557959129e9d0db8e8cTony Mantler TypedArrayUtils.getBoolean(a, R.styleable.PreferenceGroup_orderingFromXml, 8484765eaea7da18d0576db557959129e9d0db8e8cTony Mantler R.styleable.PreferenceGroup_orderingFromXml, true); 8584765eaea7da18d0576db557959129e9d0db8e8cTony Mantler 866904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler a.recycle(); 876904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 886904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 896904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler public PreferenceGroup(Context context, AttributeSet attrs, int defStyleAttr) { 906904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler this(context, attrs, defStyleAttr, 0); 916904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 926904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 936904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler public PreferenceGroup(Context context, AttributeSet attrs) { 946904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler this(context, attrs, 0); 956904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 966904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 976904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler /** 986904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * Whether to order the {@link Preference} children of this group as they 996904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * are added. If this is false, the ordering will follow each Preference 1006904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * order and default to alphabetic for those without an order. 1016904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * <p> 1026904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * If this is called after preferences are added, they will not be 1036904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * re-ordered in the order they were added, hence call this method early on. 1046904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * 1056904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * @param orderingAsAdded Whether to order according to the order added. 1066904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * @see Preference#setOrder(int) 1076904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler */ 1086904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler public void setOrderingAsAdded(boolean orderingAsAdded) { 1096904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler mOrderingAsAdded = orderingAsAdded; 1106904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 1116904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 1126904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler /** 1136904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * Whether this group is ordering preferences in the order they are added. 1146904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * 1156904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * @return Whether this group orders based on the order the children are added. 1166904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * @see #setOrderingAsAdded(boolean) 1176904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler */ 1186904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler public boolean isOrderingAsAdded() { 1196904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler return mOrderingAsAdded; 1206904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 1216904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 1226904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler /** 1236904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * Called by the inflater to add an item to this group. 1246904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler */ 1256904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler public void addItemFromInflater(Preference preference) { 1266904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler addPreference(preference); 1276904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 1286904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 1296904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler /** 1306904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * Returns the number of children {@link Preference}s. 1316904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * @return The number of preference children in this group. 1326904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler */ 1336904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler public int getPreferenceCount() { 1346904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler return mPreferenceList.size(); 1356904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 1366904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 1376904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler /** 1386904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * Returns the {@link Preference} at a particular index. 1396904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * 1406904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * @param index The index of the {@link Preference} to retrieve. 1416904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * @return The {@link Preference}. 1426904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler */ 1436904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler public Preference getPreference(int index) { 1446904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler return mPreferenceList.get(index); 1456904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 1466904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 1476904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler /** 1486904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * Adds a {@link Preference} at the correct position based on the 1496904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * preference's order. 1506904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * 1516904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * @param preference The preference to add. 1526904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * @return Whether the preference is now in this group. 1536904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler */ 1546904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler public boolean addPreference(Preference preference) { 1556904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler if (mPreferenceList.contains(preference)) { 1566904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler // Exists 1576904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler return true; 1586904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 1596904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 1606904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler if (preference.getOrder() == DEFAULT_ORDER) { 1616904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler if (mOrderingAsAdded) { 1626904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler preference.setOrder(mCurrentPreferenceOrder++); 1636904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 1646904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 1656904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler if (preference instanceof PreferenceGroup) { 1666904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler // TODO: fix (method is called tail recursively when inflating, 1676904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler // so we won't end up properly passing this flag down to children 1686904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler ((PreferenceGroup)preference).setOrderingAsAdded(mOrderingAsAdded); 1696904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 1706904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 1716904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 1726904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler int insertionIndex = Collections.binarySearch(mPreferenceList, preference); 1736904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler if (insertionIndex < 0) { 1746904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler insertionIndex = insertionIndex * -1 - 1; 1756904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 1766904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 1776904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler if (!onPrepareAddPreference(preference)) { 1786904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler return false; 1796904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 1806904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 1816904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler synchronized(this) { 1826904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler mPreferenceList.add(insertionIndex, preference); 1836904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 1846904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 185c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler final PreferenceManager preferenceManager = getPreferenceManager(); 186c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler final String key = preference.getKey(); 187c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler final long id; 188c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler if (key != null && mIdRecycleCache.containsKey(key)) { 189c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler id = mIdRecycleCache.get(key); 190c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler mIdRecycleCache.remove(key); 191c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler } else { 192c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler id = preferenceManager.getNextId(); 193c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler } 194c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler preference.onAttachedToHierarchy(preferenceManager, id); 19579af8fc48667f5fb21295fdd8cb2b5cbd4650eccFilip Pavlis preference.assignParent(this); 1966904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 197e61b4475e1837034d8926593aff9d35f8dfaebe2Tony Mantler if (mAttachedToHierarchy) { 1986904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler preference.onAttached(); 1996904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 2006904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 2016904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler notifyHierarchyChanged(); 2026904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 2036904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler return true; 2046904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 2056904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 2066904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler /** 2076904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * Removes a {@link Preference} from this group. 2086904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * 2096904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * @param preference The preference to remove. 2106904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * @return Whether the preference was found and removed. 2116904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler */ 2126904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler public boolean removePreference(Preference preference) { 2136904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler final boolean returnValue = removePreferenceInt(preference); 2146904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler notifyHierarchyChanged(); 2156904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler return returnValue; 2166904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 2176904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 2186904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler private boolean removePreferenceInt(Preference preference) { 2196904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler synchronized(this) { 2206904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler preference.onPrepareForRemoval(); 22179af8fc48667f5fb21295fdd8cb2b5cbd4650eccFilip Pavlis if (preference.getParent() == this) { 22279af8fc48667f5fb21295fdd8cb2b5cbd4650eccFilip Pavlis preference.assignParent(null); 22379af8fc48667f5fb21295fdd8cb2b5cbd4650eccFilip Pavlis } 2248f7f0d48fac8f83e90a04ba67f9a03f93c6ed262Jason Monk boolean success = mPreferenceList.remove(preference); 225c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler if (success) { 226c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler // If this preference, or another preference with the same key, gets re-added 227c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler // immediately, we want it to have the same id so that it can be correctly tracked 228c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler // in the adapter by RecyclerView, to make it appear as if it has only been 229c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler // seamlessly updated. If the preference is not re-added by the time the handler 230c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler // runs, we take that as a signal that the preference will not be re-added soon 231c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler // in which case it does not need to retain the same id. 232c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler 233c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler // If two (or more) preferences have the same (or null) key and both are removed 234c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler // and then re-added, only one id will be recycled and the second (and later) 235c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler // preferences will receive a newly generated id. This use pattern of the preference 236c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler // API is strongly discouraged. 237c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler final String key = preference.getKey(); 238c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler if (key != null) { 239c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler mIdRecycleCache.put(key, preference.getId()); 240c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler mHandler.removeCallbacks(mClearRecycleCacheRunnable); 241c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler mHandler.post(mClearRecycleCacheRunnable); 242c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler } 243c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler if (mAttachedToHierarchy) { 244c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler preference.onDetached(); 245c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler } 2468f7f0d48fac8f83e90a04ba67f9a03f93c6ed262Jason Monk } 247c4276fe96c5c73539a249bcd8c39ce8fb22859b5Tony Mantler 2488f7f0d48fac8f83e90a04ba67f9a03f93c6ed262Jason Monk return success; 2496904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 2506904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 2516904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 2526904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler /** 2536904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * Removes all {@link Preference Preferences} from this group. 2546904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler */ 2556904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler public void removeAll() { 2566904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler synchronized(this) { 2576904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler List<Preference> preferenceList = mPreferenceList; 2586904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler for (int i = preferenceList.size() - 1; i >= 0; i--) { 2596904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler removePreferenceInt(preferenceList.get(0)); 2606904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 2616904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 2626904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler notifyHierarchyChanged(); 2636904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 2646904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 2656904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler /** 2666904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * Prepares a {@link Preference} to be added to the group. 2676904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * 2686904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * @param preference The preference to add. 2696904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * @return Whether to allow adding the preference (true), or not (false). 2706904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler */ 2716904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler protected boolean onPrepareAddPreference(Preference preference) { 2726904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler preference.onParentChanged(this, shouldDisableDependents()); 2736904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler return true; 2746904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 2756904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 2766904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler /** 2776904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * Finds a {@link Preference} based on its key. If two {@link Preference} 2786904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * share the same key (not recommended), the first to appear will be 2796904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * returned (to retrieve the other preference with the same key, call this 2806904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * method on the first preference). If this preference has the key, it will 2816904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * not be returned. 2826904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * <p> 2836904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * This will recursively search for the preference into children that are 2846904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * also {@link PreferenceGroup PreferenceGroups}. 2856904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * 2866904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * @param key The key of the preference to retrieve. 2876904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * @return The {@link Preference} with the key, or null. 2886904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler */ 2896904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler public Preference findPreference(CharSequence key) { 2906904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler if (TextUtils.equals(getKey(), key)) { 2916904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler return this; 2926904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 2936904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler final int preferenceCount = getPreferenceCount(); 2946904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler for (int i = 0; i < preferenceCount; i++) { 2956904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler final Preference preference = getPreference(i); 2966904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler final String curKey = preference.getKey(); 2976904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 2986904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler if (curKey != null && curKey.equals(key)) { 2996904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler return preference; 3006904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 3016904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 3026904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler if (preference instanceof PreferenceGroup) { 3036904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler final Preference returnedPreference = ((PreferenceGroup)preference) 3046904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler .findPreference(key); 3056904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler if (returnedPreference != null) { 3066904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler return returnedPreference; 3076904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 3086904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 3096904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 3106904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 3116904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler return null; 3126904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 3136904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 3146904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler /** 3156904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * Whether this preference group should be shown on the same screen as its 3166904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * contained preferences. 3176904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * 3186904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * @return True if the contained preferences should be shown on the same 3196904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler * screen as this preference. 3206904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler */ 3216904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler protected boolean isOnSameScreenAsChildren() { 3226904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler return true; 3236904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 3246904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 32583deca7547a76f037c32fdc946173b4708b8d05bTony Mantler /** 32683deca7547a76f037c32fdc946173b4708b8d05bTony Mantler * Returns true if we're between {@link #onAttached()} and {@link #onPrepareForRemoval()} 32783deca7547a76f037c32fdc946173b4708b8d05bTony Mantler * @hide 32883deca7547a76f037c32fdc946173b4708b8d05bTony Mantler */ 3298e10080c914d1ad0784394fa3026b85535535847Aurimas Liutikas @RestrictTo(LIBRARY_GROUP) 33083deca7547a76f037c32fdc946173b4708b8d05bTony Mantler public boolean isAttached() { 33183deca7547a76f037c32fdc946173b4708b8d05bTony Mantler return mAttachedToHierarchy; 33283deca7547a76f037c32fdc946173b4708b8d05bTony Mantler } 33383deca7547a76f037c32fdc946173b4708b8d05bTony Mantler 3346904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler @Override 335e61b4475e1837034d8926593aff9d35f8dfaebe2Tony Mantler public void onAttached() { 3366904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler super.onAttached(); 3376904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 3386904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler // Mark as attached so if a preference is later added to this group, we 3396904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler // can tell it we are already attached 340e61b4475e1837034d8926593aff9d35f8dfaebe2Tony Mantler mAttachedToHierarchy = true; 3416904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 3426904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler // Dispatch to all contained preferences 3436904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler final int preferenceCount = getPreferenceCount(); 3446904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler for (int i = 0; i < preferenceCount; i++) { 3456904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler getPreference(i).onAttached(); 3466904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 3476904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 3486904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 3496904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler @Override 3508f7f0d48fac8f83e90a04ba67f9a03f93c6ed262Jason Monk public void onDetached() { 3518f7f0d48fac8f83e90a04ba67f9a03f93c6ed262Jason Monk super.onDetached(); 3526904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 3536904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler // We won't be attached to the activity anymore 354e61b4475e1837034d8926593aff9d35f8dfaebe2Tony Mantler mAttachedToHierarchy = false; 3558f7f0d48fac8f83e90a04ba67f9a03f93c6ed262Jason Monk 3568f7f0d48fac8f83e90a04ba67f9a03f93c6ed262Jason Monk // Dispatch to all contained preferences 3578f7f0d48fac8f83e90a04ba67f9a03f93c6ed262Jason Monk final int preferenceCount = getPreferenceCount(); 3588f7f0d48fac8f83e90a04ba67f9a03f93c6ed262Jason Monk for (int i = 0; i < preferenceCount; i++) { 3598f7f0d48fac8f83e90a04ba67f9a03f93c6ed262Jason Monk getPreference(i).onDetached(); 3608f7f0d48fac8f83e90a04ba67f9a03f93c6ed262Jason Monk } 3616904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 3626904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 3636904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler @Override 3646904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler public void notifyDependencyChange(boolean disableDependents) { 3656904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler super.notifyDependencyChange(disableDependents); 3666904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 3676904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler // Child preferences have an implicit dependency on their containing 3686904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler // group. Dispatch dependency change to all contained preferences. 3696904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler final int preferenceCount = getPreferenceCount(); 3706904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler for (int i = 0; i < preferenceCount; i++) { 3716904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler getPreference(i).onParentChanged(this, disableDependents); 3726904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 3736904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 3746904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 3756904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler void sortPreferences() { 3766904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler synchronized (this) { 3776904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler Collections.sort(mPreferenceList); 3786904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 3796904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 3806904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 3816904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler @Override 3826904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler protected void dispatchSaveInstanceState(Bundle container) { 3836904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler super.dispatchSaveInstanceState(container); 3846904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 3856904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler // Dispatch to all contained preferences 3866904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler final int preferenceCount = getPreferenceCount(); 3876904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler for (int i = 0; i < preferenceCount; i++) { 3886904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler getPreference(i).dispatchSaveInstanceState(container); 3896904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 3906904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 3916904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 3926904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler @Override 3936904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler protected void dispatchRestoreInstanceState(Bundle container) { 3946904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler super.dispatchRestoreInstanceState(container); 3956904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 3966904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler // Dispatch to all contained preferences 3976904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler final int preferenceCount = getPreferenceCount(); 3986904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler for (int i = 0; i < preferenceCount; i++) { 3996904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler getPreference(i).dispatchRestoreInstanceState(container); 4006904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 4016904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler } 4026904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler 40366222008cbda61251014caf1442930a48561d25cTony Mantler /** 40466222008cbda61251014caf1442930a48561d25cTony Mantler * Interface for PreferenceGroup Adapters to implement so that 40566222008cbda61251014caf1442930a48561d25cTony Mantler * {@link android.support.v14.preference.PreferenceFragment#scrollToPreference(String)} and 40666222008cbda61251014caf1442930a48561d25cTony Mantler * {@link android.support.v14.preference.PreferenceFragment#scrollToPreference(Preference)} or 40766222008cbda61251014caf1442930a48561d25cTony Mantler * {@link PreferenceFragmentCompat#scrollToPreference(String)} and 40866222008cbda61251014caf1442930a48561d25cTony Mantler * {@link PreferenceFragmentCompat#scrollToPreference(Preference)} 40966222008cbda61251014caf1442930a48561d25cTony Mantler * can determine the correct scroll position to request. 41066222008cbda61251014caf1442930a48561d25cTony Mantler */ 41166222008cbda61251014caf1442930a48561d25cTony Mantler public interface PreferencePositionCallback { 41266222008cbda61251014caf1442930a48561d25cTony Mantler 41366222008cbda61251014caf1442930a48561d25cTony Mantler /** 41466222008cbda61251014caf1442930a48561d25cTony Mantler * Return the adapter position of the first {@link Preference} with the specified key 41566222008cbda61251014caf1442930a48561d25cTony Mantler * @param key Key of {@link Preference} 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(String key); 42066222008cbda61251014caf1442930a48561d25cTony Mantler 42166222008cbda61251014caf1442930a48561d25cTony Mantler /** 42266222008cbda61251014caf1442930a48561d25cTony Mantler * Return the adapter position of the specified {@link Preference} object 42366222008cbda61251014caf1442930a48561d25cTony Mantler * @param preference {@link Preference} object to find 42466222008cbda61251014caf1442930a48561d25cTony Mantler * @return Adapter position of the {@link Preference} or 42566222008cbda61251014caf1442930a48561d25cTony Mantler * {@link android.support.v7.widget.RecyclerView#NO_POSITION} if not found 42666222008cbda61251014caf1442930a48561d25cTony Mantler */ 42766222008cbda61251014caf1442930a48561d25cTony Mantler int getPreferenceAdapterPosition(Preference preference); 42866222008cbda61251014caf1442930a48561d25cTony Mantler } 4296904f67c96a28a0e5966b4fb6d37a0ad5f136858Tony Mantler} 430