1a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell/* 2a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Copyright (C) 2015 The Android Open Source Project 3a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 4a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Licensed under the Apache License, Version 2.0 (the "License"); 5a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * you may not use this file except in compliance with the License. 6a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * You may obtain a copy of the License at 7a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 8a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * http://www.apache.org/licenses/LICENSE-2.0 9a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 10a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Unless required by applicable law or agreed to in writing, software 11a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * distributed under the License is distributed on an "AS IS" BASIS, 12a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * See the License for the specific language governing permissions and 14a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * limitations under the License. 15a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 16a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 17a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellpackage android.support.design.widget; 18a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 19a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.content.Context; 20a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.content.res.Resources; 21a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.content.res.TypedArray; 22a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.graphics.Canvas; 23a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.graphics.Color; 24a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.graphics.Paint; 25a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.graphics.Rect; 2675284fffafacd32f4d178020050589f9e70e5ed9Chris Banesimport android.graphics.drawable.ColorDrawable; 2775284fffafacd32f4d178020050589f9e70e5ed9Chris Banesimport android.graphics.drawable.Drawable; 28a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.os.Build; 29e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banesimport android.os.Parcel; 30e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banesimport android.os.Parcelable; 31a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.os.SystemClock; 32bcb330de0c625b371010bada2a51363fc37b52ccChris Banesimport android.support.annotation.ColorInt; 33bcb330de0c625b371010bada2a51363fc37b52ccChris Banesimport android.support.annotation.DrawableRes; 34bcb330de0c625b371010bada2a51363fc37b52ccChris Banesimport android.support.annotation.Nullable; 35a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.support.design.R; 3675284fffafacd32f4d178020050589f9e70e5ed9Chris Banesimport android.support.v4.content.ContextCompat; 37bcb330de0c625b371010bada2a51363fc37b52ccChris Banesimport android.support.v4.graphics.drawable.DrawableCompat; 3862ab25d71ccfa775a8bd2add7b41277bc4e14bbcChris Banesimport android.support.v4.os.ParcelableCompat; 3962ab25d71ccfa775a8bd2add7b41277bc4e14bbcChris Banesimport android.support.v4.os.ParcelableCompatCreatorCallbacks; 4005f5ba020fa6caa658c75b6d77436aa980ca0fccChris Banesimport android.support.v4.view.AbsSavedState; 41a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.support.v4.view.GravityCompat; 4288cccf6c76b6a1c2d67152c2de5599f3c8301b18Chris Banesimport android.support.v4.view.MotionEventCompat; 43a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.support.v4.view.NestedScrollingParent; 44a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.support.v4.view.NestedScrollingParentHelper; 45a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.support.v4.view.ViewCompat; 4675284fffafacd32f4d178020050589f9e70e5ed9Chris Banesimport android.support.v4.view.WindowInsetsCompat; 47a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.text.TextUtils; 48a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.util.AttributeSet; 49a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.util.Log; 50e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banesimport android.util.SparseArray; 51a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.view.Gravity; 52a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.view.MotionEvent; 53a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.view.View; 54a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.view.ViewGroup; 55a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.view.ViewParent; 56a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.view.ViewTreeObserver; 57a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 58a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport java.lang.annotation.Retention; 59a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport java.lang.annotation.RetentionPolicy; 60a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport java.lang.reflect.Constructor; 61a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport java.util.ArrayList; 62a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport java.util.Collections; 63a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport java.util.Comparator; 64a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport java.util.HashMap; 65a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport java.util.List; 66a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport java.util.Map; 67a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 68a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell/** 69a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * CoordinatorLayout is a super-powered {@link android.widget.FrameLayout FrameLayout}. 70a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 71a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>CoordinatorLayout is intended for two primary use cases:</p> 72a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <ol> 73a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <li>As a top-level application decor or chrome layout</li> 74a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <li>As a container for a specific interaction with one or more child views</li> 75a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * </ol> 76a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 77a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>By specifying {@link CoordinatorLayout.Behavior Behaviors} for child views of a 78a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * CoordinatorLayout you can provide many different interactions within a single parent and those 79a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * views can also interact with one another. View classes can specify a default behavior when 80a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * used as a child of a CoordinatorLayout using the 81a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link CoordinatorLayout.DefaultBehavior DefaultBehavior} annotation.</p> 82a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 83a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>Behaviors may be used to implement a variety of interactions and additional layout 84a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * modifications ranging from sliding drawers and panels to swipe-dismissable elements and buttons 85a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * that stick to other elements as they move and animate.</p> 86a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 87a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>Children of a CoordinatorLayout may have an 88a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link CoordinatorLayout.LayoutParams#setAnchorId(int) anchor}. This view id must correspond 89a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * to an arbitrary descendant of the CoordinatorLayout, but it may not be the anchored child itself 90a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * or a descendant of the anchored child. This can be used to place floating views relative to 91a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * other arbitrary content panes.</p> 92a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 93a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellpublic class CoordinatorLayout extends ViewGroup implements NestedScrollingParent { 94a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell static final String TAG = "CoordinatorLayout"; 9525ef4026b72ff670ee07c81897124732d3f5f443Chris Banes static final String WIDGET_PACKAGE_NAME; 9625ef4026b72ff670ee07c81897124732d3f5f443Chris Banes 9725ef4026b72ff670ee07c81897124732d3f5f443Chris Banes static { 9825ef4026b72ff670ee07c81897124732d3f5f443Chris Banes final Package pkg = CoordinatorLayout.class.getPackage(); 9925ef4026b72ff670ee07c81897124732d3f5f443Chris Banes WIDGET_PACKAGE_NAME = pkg != null ? pkg.getName() : null; 10025ef4026b72ff670ee07c81897124732d3f5f443Chris Banes } 101a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 102d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes private static final int TYPE_ON_INTERCEPT = 0; 103d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes private static final int TYPE_ON_TOUCH = 1; 104d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes 105a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell static { 106a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes if (Build.VERSION.SDK_INT >= 21) { 107a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell TOP_SORTED_CHILDREN_COMPARATOR = new ViewElevationComparator(); 10875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes INSETS_HELPER = new CoordinatorLayoutInsetsHelperLollipop(); 109a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else { 110a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell TOP_SORTED_CHILDREN_COMPARATOR = null; 11175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes INSETS_HELPER = null; 112a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 113a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 114a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 115a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell static final Class<?>[] CONSTRUCTOR_PARAMS = new Class<?>[] { 116a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Context.class, 117a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell AttributeSet.class 118a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell }; 119a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 120a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell static final ThreadLocal<Map<String, Constructor<Behavior>>> sConstructors = 121a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell new ThreadLocal<>(); 122a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 123a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Comparator<View> mLayoutDependencyComparator = new Comparator<View>() { 124a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 125a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public int compare(View lhs, View rhs) { 126a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (lhs == rhs) { 127a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return 0; 128a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else if (((LayoutParams) lhs.getLayoutParams()).dependsOn( 129a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell CoordinatorLayout.this, lhs, rhs)) { 130a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return 1; 131a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else if (((LayoutParams) rhs.getLayoutParams()).dependsOn( 132a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell CoordinatorLayout.this, rhs, lhs)) { 133a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return -1; 134a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else { 135a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return 0; 136a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 137a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 138a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell }; 139a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 140a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell static final Comparator<View> TOP_SORTED_CHILDREN_COMPARATOR; 14175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes static final CoordinatorLayoutInsetsHelper INSETS_HELPER; 142a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 143a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private final List<View> mDependencySortedChildren = new ArrayList<View>(); 144a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes private final List<View> mTempList1 = new ArrayList<>(); 145a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes private final List<View> mTempDependenciesList = new ArrayList<>(); 146a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private final Rect mTempRect1 = new Rect(); 147a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private final Rect mTempRect2 = new Rect(); 148a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private final Rect mTempRect3 = new Rect(); 1495cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell private final int[] mTempIntPair = new int[2]; 150a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private Paint mScrimPaint; 151a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 15278d6f4ad1fc1e2d57b138e31f47f2267731ee95eAurimas Liutikas private boolean mDisallowInterceptReset; 15378d6f4ad1fc1e2d57b138e31f47f2267731ee95eAurimas Liutikas 154a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private boolean mIsAttachedToWindow; 155a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 156a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private int[] mKeylines; 157a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 158a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private View mBehaviorTouchView; 1595cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell private View mNestedScrollingDirectChild; 1605cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell private View mNestedScrollingTarget; 161a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 162a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private OnPreDrawListener mOnPreDrawListener; 163a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private boolean mNeedsPreDrawListener; 164a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 16575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes private WindowInsetsCompat mLastInsets; 16675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes private boolean mDrawStatusBarBackground; 16775284fffafacd32f4d178020050589f9e70e5ed9Chris Banes private Drawable mStatusBarBackground; 16875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 1690b00489086b22c9688c8c04990dadf54489d45e3Chris Banes private OnHierarchyChangeListener mOnHierarchyChangeListener; 1700b00489086b22c9688c8c04990dadf54489d45e3Chris Banes 171a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private final NestedScrollingParentHelper mNestedScrollingParentHelper = 172a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell new NestedScrollingParentHelper(this); 173a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 174a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public CoordinatorLayout(Context context) { 175a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell this(context, null); 176a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 177a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 178a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public CoordinatorLayout(Context context, AttributeSet attrs) { 179a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell this(context, attrs, 0); 180a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 181a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 182a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public CoordinatorLayout(Context context, AttributeSet attrs, int defStyleAttr) { 183a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell super(context, attrs, defStyleAttr); 184a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 185809bb62055ad42b88f3a69308be222801b89fbd9Chris Banes ThemeUtils.checkAppCompatTheme(context); 186809bb62055ad42b88f3a69308be222801b89fbd9Chris Banes 187a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CoordinatorLayout, 18875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes defStyleAttr, R.style.Widget_Design_CoordinatorLayout); 189a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int keylineArrayRes = a.getResourceId(R.styleable.CoordinatorLayout_keylines, 0); 190a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (keylineArrayRes != 0) { 191a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Resources res = context.getResources(); 192a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mKeylines = res.getIntArray(keylineArrayRes); 193a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final float density = res.getDisplayMetrics().density; 194a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int count = mKeylines.length; 195a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int i = 0; i < count; i++) { 196a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mKeylines[i] *= density; 197a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 198a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 19975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes mStatusBarBackground = a.getDrawable(R.styleable.CoordinatorLayout_statusBarBackground); 200a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell a.recycle(); 20175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 20275284fffafacd32f4d178020050589f9e70e5ed9Chris Banes if (INSETS_HELPER != null) { 20375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes INSETS_HELPER.setupForWindowInsets(this, new ApplyInsetsListener()); 20475284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 2050b00489086b22c9688c8c04990dadf54489d45e3Chris Banes super.setOnHierarchyChangeListener(new HierarchyChangeListener()); 2060b00489086b22c9688c8c04990dadf54489d45e3Chris Banes } 2070b00489086b22c9688c8c04990dadf54489d45e3Chris Banes 2080b00489086b22c9688c8c04990dadf54489d45e3Chris Banes @Override 2090b00489086b22c9688c8c04990dadf54489d45e3Chris Banes public void setOnHierarchyChangeListener(OnHierarchyChangeListener onHierarchyChangeListener) { 2100b00489086b22c9688c8c04990dadf54489d45e3Chris Banes mOnHierarchyChangeListener = onHierarchyChangeListener; 211a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 212a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 213a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 214a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public void onAttachedToWindow() { 215a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell super.onAttachedToWindow(); 2165cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell resetTouchBehaviors(); 217a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mNeedsPreDrawListener) { 218a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mOnPreDrawListener == null) { 219a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mOnPreDrawListener = new OnPreDrawListener(); 220a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 221a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final ViewTreeObserver vto = getViewTreeObserver(); 222a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell vto.addOnPreDrawListener(mOnPreDrawListener); 223a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 224e3f6ba486fec4e11ca7508049ac81de4c7102f23Chris Banes if (mLastInsets == null && ViewCompat.getFitsSystemWindows(this)) { 225e3f6ba486fec4e11ca7508049ac81de4c7102f23Chris Banes // We're set to fitSystemWindows but we haven't had any insets yet... 226e3f6ba486fec4e11ca7508049ac81de4c7102f23Chris Banes // We should request a new dispatch of window insets 227e3f6ba486fec4e11ca7508049ac81de4c7102f23Chris Banes ViewCompat.requestApplyInsets(this); 228e3f6ba486fec4e11ca7508049ac81de4c7102f23Chris Banes } 229a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mIsAttachedToWindow = true; 230a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 231a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 232a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 233a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public void onDetachedFromWindow() { 234a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell super.onDetachedFromWindow(); 2355cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell resetTouchBehaviors(); 236a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mNeedsPreDrawListener && mOnPreDrawListener != null) { 237a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final ViewTreeObserver vto = getViewTreeObserver(); 238a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell vto.removeOnPreDrawListener(mOnPreDrawListener); 239a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2405cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (mNestedScrollingTarget != null) { 2415cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell onStopNestedScroll(mNestedScrollingTarget); 2425cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 243a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mIsAttachedToWindow = false; 244a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 245a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 246a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 24775284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * Set a drawable to draw in the insets area for the status bar. 24875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * Note that this will only be activated if this DrawerLayout fitsSystemWindows. 24975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * 25075284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * @param bg Background drawable to draw behind the status bar 25175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes */ 252bcb330de0c625b371010bada2a51363fc37b52ccChris Banes public void setStatusBarBackground(@Nullable final Drawable bg) { 253bcb330de0c625b371010bada2a51363fc37b52ccChris Banes if (mStatusBarBackground != bg) { 254bcb330de0c625b371010bada2a51363fc37b52ccChris Banes if (mStatusBarBackground != null) { 255bcb330de0c625b371010bada2a51363fc37b52ccChris Banes mStatusBarBackground.setCallback(null); 256bcb330de0c625b371010bada2a51363fc37b52ccChris Banes } 257bcb330de0c625b371010bada2a51363fc37b52ccChris Banes mStatusBarBackground = bg != null ? bg.mutate() : null; 258bcb330de0c625b371010bada2a51363fc37b52ccChris Banes if (mStatusBarBackground != null) { 259bcb330de0c625b371010bada2a51363fc37b52ccChris Banes if (mStatusBarBackground.isStateful()) { 260bcb330de0c625b371010bada2a51363fc37b52ccChris Banes mStatusBarBackground.setState(getDrawableState()); 261bcb330de0c625b371010bada2a51363fc37b52ccChris Banes } 262bcb330de0c625b371010bada2a51363fc37b52ccChris Banes DrawableCompat.setLayoutDirection(mStatusBarBackground, 263bcb330de0c625b371010bada2a51363fc37b52ccChris Banes ViewCompat.getLayoutDirection(this)); 264bcb330de0c625b371010bada2a51363fc37b52ccChris Banes mStatusBarBackground.setVisible(getVisibility() == VISIBLE, false); 265bcb330de0c625b371010bada2a51363fc37b52ccChris Banes mStatusBarBackground.setCallback(this); 266bcb330de0c625b371010bada2a51363fc37b52ccChris Banes } 267bcb330de0c625b371010bada2a51363fc37b52ccChris Banes ViewCompat.postInvalidateOnAnimation(this); 268bcb330de0c625b371010bada2a51363fc37b52ccChris Banes } 26975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 27075284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 27175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes /** 27275284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * Gets the drawable used to draw in the insets area for the status bar. 27375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * 27475284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * @return The status bar background drawable, or null if none set 27575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes */ 276bcb330de0c625b371010bada2a51363fc37b52ccChris Banes @Nullable 27775284fffafacd32f4d178020050589f9e70e5ed9Chris Banes public Drawable getStatusBarBackground() { 27875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes return mStatusBarBackground; 27975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 28075284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 281bcb330de0c625b371010bada2a51363fc37b52ccChris Banes @Override 282bcb330de0c625b371010bada2a51363fc37b52ccChris Banes protected void drawableStateChanged() { 283bcb330de0c625b371010bada2a51363fc37b52ccChris Banes super.drawableStateChanged(); 284bcb330de0c625b371010bada2a51363fc37b52ccChris Banes 285bcb330de0c625b371010bada2a51363fc37b52ccChris Banes final int[] state = getDrawableState(); 286bcb330de0c625b371010bada2a51363fc37b52ccChris Banes boolean changed = false; 287bcb330de0c625b371010bada2a51363fc37b52ccChris Banes 288bcb330de0c625b371010bada2a51363fc37b52ccChris Banes Drawable d = mStatusBarBackground; 289bcb330de0c625b371010bada2a51363fc37b52ccChris Banes if (d != null && d.isStateful()) { 290bcb330de0c625b371010bada2a51363fc37b52ccChris Banes changed |= d.setState(state); 291bcb330de0c625b371010bada2a51363fc37b52ccChris Banes } 292bcb330de0c625b371010bada2a51363fc37b52ccChris Banes 293bcb330de0c625b371010bada2a51363fc37b52ccChris Banes if (changed) { 294bcb330de0c625b371010bada2a51363fc37b52ccChris Banes invalidate(); 295bcb330de0c625b371010bada2a51363fc37b52ccChris Banes } 296bcb330de0c625b371010bada2a51363fc37b52ccChris Banes } 297bcb330de0c625b371010bada2a51363fc37b52ccChris Banes 298bcb330de0c625b371010bada2a51363fc37b52ccChris Banes @Override 299bcb330de0c625b371010bada2a51363fc37b52ccChris Banes protected boolean verifyDrawable(Drawable who) { 300bcb330de0c625b371010bada2a51363fc37b52ccChris Banes return super.verifyDrawable(who) || who == mStatusBarBackground; 301bcb330de0c625b371010bada2a51363fc37b52ccChris Banes } 302bcb330de0c625b371010bada2a51363fc37b52ccChris Banes 303bcb330de0c625b371010bada2a51363fc37b52ccChris Banes @Override 304bcb330de0c625b371010bada2a51363fc37b52ccChris Banes public void setVisibility(int visibility) { 305bcb330de0c625b371010bada2a51363fc37b52ccChris Banes super.setVisibility(visibility); 306bcb330de0c625b371010bada2a51363fc37b52ccChris Banes 307bcb330de0c625b371010bada2a51363fc37b52ccChris Banes final boolean visible = visibility == VISIBLE; 308bcb330de0c625b371010bada2a51363fc37b52ccChris Banes if (mStatusBarBackground != null && mStatusBarBackground.isVisible() != visible) { 309bcb330de0c625b371010bada2a51363fc37b52ccChris Banes mStatusBarBackground.setVisible(visible, false); 310bcb330de0c625b371010bada2a51363fc37b52ccChris Banes } 311bcb330de0c625b371010bada2a51363fc37b52ccChris Banes } 312bcb330de0c625b371010bada2a51363fc37b52ccChris Banes 31375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes /** 31475284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * Set a drawable to draw in the insets area for the status bar. 31575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * Note that this will only be activated if this DrawerLayout fitsSystemWindows. 31675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * 31775284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * @param resId Resource id of a background drawable to draw behind the status bar 31875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes */ 319bcb330de0c625b371010bada2a51363fc37b52ccChris Banes public void setStatusBarBackgroundResource(@DrawableRes int resId) { 32075284fffafacd32f4d178020050589f9e70e5ed9Chris Banes setStatusBarBackground(resId != 0 ? ContextCompat.getDrawable(getContext(), resId) : null); 32175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 32275284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 32375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes /** 32475284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * Set a drawable to draw in the insets area for the status bar. 32575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * Note that this will only be activated if this DrawerLayout fitsSystemWindows. 32675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * 32775284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * @param color Color to use as a background drawable to draw behind the status bar 32875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * in 0xAARRGGBB format. 32975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes */ 330bcb330de0c625b371010bada2a51363fc37b52ccChris Banes public void setStatusBarBackgroundColor(@ColorInt int color) { 33175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes setStatusBarBackground(new ColorDrawable(color)); 33275284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 33375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 33417ed3263761329f6aa6796941358c41001fff325Chris Banes private WindowInsetsCompat setWindowInsets(WindowInsetsCompat insets) { 33575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes if (mLastInsets != insets) { 33675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes mLastInsets = insets; 33775284fffafacd32f4d178020050589f9e70e5ed9Chris Banes mDrawStatusBarBackground = insets != null && insets.getSystemWindowInsetTop() > 0; 33875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes setWillNotDraw(!mDrawStatusBarBackground && getBackground() == null); 33917ed3263761329f6aa6796941358c41001fff325Chris Banes 34017ed3263761329f6aa6796941358c41001fff325Chris Banes // Now dispatch to the Behaviors 34117ed3263761329f6aa6796941358c41001fff325Chris Banes insets = dispatchApplyWindowInsetsToBehaviors(insets); 34275284fffafacd32f4d178020050589f9e70e5ed9Chris Banes requestLayout(); 34375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 34417ed3263761329f6aa6796941358c41001fff325Chris Banes return insets; 34575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 34675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 3472e522d2998c937948757ccfe0a5523047726fb4dChris Banes final WindowInsetsCompat getLastWindowInsets() { 3482e522d2998c937948757ccfe0a5523047726fb4dChris Banes return mLastInsets; 3492e522d2998c937948757ccfe0a5523047726fb4dChris Banes } 3502e522d2998c937948757ccfe0a5523047726fb4dChris Banes 35175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes /** 352a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Reset all Behavior-related tracking records either to clean up or in preparation 353a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * for a new event stream. This should be called when attached or detached from a window, 354a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * in response to an UP or CANCEL event, when intercept is request-disallowed 355a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * and similar cases where an event stream in progress will be aborted. 356a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 3575cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell private void resetTouchBehaviors() { 358a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mBehaviorTouchView != null) { 359a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Behavior b = ((LayoutParams) mBehaviorTouchView.getLayoutParams()).getBehavior(); 360a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (b != null) { 361a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final long now = SystemClock.uptimeMillis(); 362a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final MotionEvent cancelEvent = MotionEvent.obtain(now, now, 363a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0); 364a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell b.onTouchEvent(this, mBehaviorTouchView, cancelEvent); 365a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell cancelEvent.recycle(); 366a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 367a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mBehaviorTouchView = null; 368a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 369a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 370a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childCount = getChildCount(); 371a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int i = 0; i < childCount; i++) { 372a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final View child = getChildAt(i); 373a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 374a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell lp.resetTouchBehaviorTracking(); 375a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 37678d6f4ad1fc1e2d57b138e31f47f2267731ee95eAurimas Liutikas mDisallowInterceptReset = false; 377a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 378a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 379a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 380a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Populate a list with the current child views, sorted such that the topmost views 381a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * in z-order are at the front of the list. Useful for hit testing and event dispatch. 382a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 383a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private void getTopSortedChildren(List<View> out) { 384a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell out.clear(); 385a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 386a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final boolean useCustomOrder = isChildrenDrawingOrderEnabled(); 387a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childCount = getChildCount(); 388a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int i = childCount - 1; i >= 0; i--) { 389a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childIndex = useCustomOrder ? getChildDrawingOrder(childCount, i) : i; 390a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final View child = getChildAt(childIndex); 391a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell out.add(child); 392a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 393a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 394a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (TOP_SORTED_CHILDREN_COMPARATOR != null) { 395a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Collections.sort(out, TOP_SORTED_CHILDREN_COMPARATOR); 396a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 397a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 398a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 399d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes private boolean performIntercept(MotionEvent ev, final int type) { 400a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean intercepted = false; 401a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean newBlock = false; 402a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 403a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell MotionEvent cancelEvent = null; 404a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 40588cccf6c76b6a1c2d67152c2de5599f3c8301b18Chris Banes final int action = MotionEventCompat.getActionMasked(ev); 406a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 407a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes final List<View> topmostChildList = mTempList1; 408a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getTopSortedChildren(topmostChildList); 409a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 410a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Let topmost child views inspect first 411a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childCount = topmostChildList.size(); 412a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int i = 0; i < childCount; i++) { 413a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final View child = topmostChildList.get(i); 414a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 415a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Behavior b = lp.getBehavior(); 416a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 417a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if ((intercepted || newBlock) && action != MotionEvent.ACTION_DOWN) { 418a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Cancel all behaviors beneath the one that intercepted. 419a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // If the event is "down" then we don't have anything to cancel yet. 420a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (b != null) { 421515613db9b9d82472c8fce69b2b104c277f68b99Chris Banes if (cancelEvent == null) { 422a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final long now = SystemClock.uptimeMillis(); 423a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell cancelEvent = MotionEvent.obtain(now, now, 424a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0); 425a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 426d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes switch (type) { 427d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes case TYPE_ON_INTERCEPT: 428d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes b.onInterceptTouchEvent(this, child, cancelEvent); 429d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes break; 430d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes case TYPE_ON_TOUCH: 431d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes b.onTouchEvent(this, child, cancelEvent); 432d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes break; 433d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes } 434a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 435a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell continue; 436a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 437a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 438d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes if (!intercepted && b != null) { 439d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes switch (type) { 440d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes case TYPE_ON_INTERCEPT: 441d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes intercepted = b.onInterceptTouchEvent(this, child, ev); 442d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes break; 443d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes case TYPE_ON_TOUCH: 444d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes intercepted = b.onTouchEvent(this, child, ev); 445d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes break; 446d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes } 447d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes if (intercepted) { 448d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes mBehaviorTouchView = child; 449d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes } 450a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 451a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 452a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Don't keep going if we're not allowing interaction below this. 453a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Setting newBlock will make sure we cancel the rest of the behaviors. 454a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final boolean wasBlocking = lp.didBlockInteraction(); 455a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final boolean isBlocking = lp.isBlockingInteractionBelow(this, child); 456a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell newBlock = isBlocking && !wasBlocking; 457a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (isBlocking && !newBlock) { 458a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Stop here since we don't have anything more to cancel - we already did 459a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // when the behavior first started blocking things below this point. 460a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 461a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 462a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 463a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 464a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell topmostChildList.clear(); 465a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 466a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return intercepted; 467a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 468a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 469a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 470a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean onInterceptTouchEvent(MotionEvent ev) { 471a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell MotionEvent cancelEvent = null; 472a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 47388cccf6c76b6a1c2d67152c2de5599f3c8301b18Chris Banes final int action = MotionEventCompat.getActionMasked(ev); 474a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 475a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Make sure we reset in case we had missed a previous important event. 476a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (action == MotionEvent.ACTION_DOWN) { 4775cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell resetTouchBehaviors(); 478a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 479a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 480d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes final boolean intercepted = performIntercept(ev, TYPE_ON_INTERCEPT); 481a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 482a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (cancelEvent != null) { 483a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell cancelEvent.recycle(); 484a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 485a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 486a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { 4875cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell resetTouchBehaviors(); 488a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 489a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 490a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return intercepted; 491a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 492a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 493a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 494a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean onTouchEvent(MotionEvent ev) { 495a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean handled = false; 496a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean cancelSuper = false; 497a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell MotionEvent cancelEvent = null; 498a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 49988cccf6c76b6a1c2d67152c2de5599f3c8301b18Chris Banes final int action = MotionEventCompat.getActionMasked(ev); 500a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 501d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes if (mBehaviorTouchView != null || (cancelSuper = performIntercept(ev, TYPE_ON_TOUCH))) { 502a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Safe since performIntercept guarantees that 503a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // mBehaviorTouchView != null if it returns true 504ecc58a45a7bdd60d9b71e6c413b80a3f8cf85822Chris Banes final LayoutParams lp = (LayoutParams) mBehaviorTouchView.getLayoutParams(); 505ecc58a45a7bdd60d9b71e6c413b80a3f8cf85822Chris Banes final Behavior b = lp.getBehavior(); 506ecc58a45a7bdd60d9b71e6c413b80a3f8cf85822Chris Banes if (b != null) { 507d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes handled = b.onTouchEvent(this, mBehaviorTouchView, ev); 508ecc58a45a7bdd60d9b71e6c413b80a3f8cf85822Chris Banes } 509a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 510a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 511a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Keep the super implementation correct 512a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mBehaviorTouchView == null) { 513a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell handled |= super.onTouchEvent(ev); 514a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else if (cancelSuper) { 515ea004a01f44aaf36212120c936952c1742d03d30Chris Banes if (cancelEvent == null) { 516a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final long now = SystemClock.uptimeMillis(); 517a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell cancelEvent = MotionEvent.obtain(now, now, 518a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0); 519a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 520a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell super.onTouchEvent(cancelEvent); 521a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 522a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 523a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (!handled && action == MotionEvent.ACTION_DOWN) { 524a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 525a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 526a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 527a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (cancelEvent != null) { 528a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell cancelEvent.recycle(); 529a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 530a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 531a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { 5325cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell resetTouchBehaviors(); 533a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 534a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 535a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return handled; 536a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 537a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 538a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 539a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) { 540a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell super.requestDisallowInterceptTouchEvent(disallowIntercept); 54178d6f4ad1fc1e2d57b138e31f47f2267731ee95eAurimas Liutikas if (disallowIntercept && !mDisallowInterceptReset) { 5425cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell resetTouchBehaviors(); 54378d6f4ad1fc1e2d57b138e31f47f2267731ee95eAurimas Liutikas mDisallowInterceptReset = true; 544a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 545a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 546a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 547a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private int getKeyline(int index) { 548a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mKeylines == null) { 549a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Log.e(TAG, "No keylines defined for " + this + " - attempted index lookup " + index); 550a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return 0; 551a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 552a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 553a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (index < 0 || index >= mKeylines.length) { 554a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Log.e(TAG, "Keyline index " + index + " out of range for " + this); 555a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return 0; 556a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 557a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 558a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return mKeylines[index]; 559a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 560a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 561a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell static Behavior parseBehavior(Context context, AttributeSet attrs, String name) { 562a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (TextUtils.isEmpty(name)) { 563a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return null; 564a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 565a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 566a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final String fullName; 567a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (name.startsWith(".")) { 568a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Relative to the app package. Prepend the app package name. 569a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell fullName = context.getPackageName() + name; 570a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else if (name.indexOf('.') >= 0) { 571a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Fully qualified package name. 572a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell fullName = name; 573a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else { 57425ef4026b72ff670ee07c81897124732d3f5f443Chris Banes // Assume stock behavior in this package (if we have one) 57525ef4026b72ff670ee07c81897124732d3f5f443Chris Banes fullName = !TextUtils.isEmpty(WIDGET_PACKAGE_NAME) 57625ef4026b72ff670ee07c81897124732d3f5f443Chris Banes ? (WIDGET_PACKAGE_NAME + '.' + name) 57725ef4026b72ff670ee07c81897124732d3f5f443Chris Banes : name; 578a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 579a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 580a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell try { 581a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Map<String, Constructor<Behavior>> constructors = sConstructors.get(); 582a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (constructors == null) { 583a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell constructors = new HashMap<>(); 584a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell sConstructors.set(constructors); 585a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 586a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Constructor<Behavior> c = constructors.get(fullName); 587a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (c == null) { 588a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Class<Behavior> clazz = (Class<Behavior>) Class.forName(fullName, true, 589a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell context.getClassLoader()); 590a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell c = clazz.getConstructor(CONSTRUCTOR_PARAMS); 591878384f1e6de7bd9196958224ced1ecfca3be6a7Chris Banes c.setAccessible(true); 592a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell constructors.put(fullName, c); 593a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 594a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return c.newInstance(context, attrs); 595a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } catch (Exception e) { 596a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell throw new RuntimeException("Could not inflate Behavior subclass " + fullName, e); 597a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 598a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 599a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 600a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell LayoutParams getResolvedLayoutParams(View child) { 601a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams result = (LayoutParams) child.getLayoutParams(); 602a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (!result.mBehaviorResolved) { 60342058bc54bdb89b9c9429bf6cbd3260787cf0523Adam Powell Class<?> childClass = child.getClass(); 60442058bc54bdb89b9c9429bf6cbd3260787cf0523Adam Powell DefaultBehavior defaultBehavior = null; 60542058bc54bdb89b9c9429bf6cbd3260787cf0523Adam Powell while (childClass != null && 60642058bc54bdb89b9c9429bf6cbd3260787cf0523Adam Powell (defaultBehavior = childClass.getAnnotation(DefaultBehavior.class)) == null) { 60742058bc54bdb89b9c9429bf6cbd3260787cf0523Adam Powell childClass = childClass.getSuperclass(); 60842058bc54bdb89b9c9429bf6cbd3260787cf0523Adam Powell } 609a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (defaultBehavior != null) { 610a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell try { 611a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell result.setBehavior(defaultBehavior.value().newInstance()); 612a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } catch (Exception e) { 613a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Log.e(TAG, "Default behavior class " + defaultBehavior.value().getName() + 614a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell " could not be instantiated. Did you forget a default constructor?", e); 615a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 616a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 617a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell result.mBehaviorResolved = true; 618a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 619a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return result; 620a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 621a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 622a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private void prepareChildren() { 6238248a6287c4ff9fa71ff6760bb6fe0906f0d6607Chris Banes mDependencySortedChildren.clear(); 6248248a6287c4ff9fa71ff6760bb6fe0906f0d6607Chris Banes for (int i = 0, count = getChildCount(); i < count; i++) { 625a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final View child = getChildAt(i); 6268248a6287c4ff9fa71ff6760bb6fe0906f0d6607Chris Banes 627a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = getResolvedLayoutParams(child); 628a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell lp.findAnchorView(this, child); 629a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 6308248a6287c4ff9fa71ff6760bb6fe0906f0d6607Chris Banes mDependencySortedChildren.add(child); 631a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 6328248a6287c4ff9fa71ff6760bb6fe0906f0d6607Chris Banes // We need to use a selection sort here to make sure that every item is compared 6338248a6287c4ff9fa71ff6760bb6fe0906f0d6607Chris Banes // against each other 6348248a6287c4ff9fa71ff6760bb6fe0906f0d6607Chris Banes selectionSort(mDependencySortedChildren, mLayoutDependencyComparator); 635a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 636a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 637a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 638a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Retrieve the transformed bounding rect of an arbitrary descendant view. 639a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * This does not need to be a direct child. 640a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 641a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param descendant descendant view to reference 642a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param out rect to set to the bounds of the descendant view 643a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 644a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void getDescendantRect(View descendant, Rect out) { 645a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes ViewGroupUtils.getDescendantRect(this, descendant, out); 646a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 647a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 648a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 649a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell protected int getSuggestedMinimumWidth() { 650a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return Math.max(super.getSuggestedMinimumWidth(), getPaddingLeft() + getPaddingRight()); 651a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 652a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 653a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 654a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell protected int getSuggestedMinimumHeight() { 655a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return Math.max(super.getSuggestedMinimumHeight(), getPaddingTop() + getPaddingBottom()); 656a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 657a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 658a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 659a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Called to measure each individual child view unless a 660a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link CoordinatorLayout.Behavior Behavior} is present. The Behavior may choose to delegate 661a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * child measurement to this method. 662a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 663a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child to measure 664a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parentWidthMeasureSpec the width requirements for this view 665a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param widthUsed extra space that has been used up by the parent 666a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * horizontally (possibly by other children of the parent) 667a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parentHeightMeasureSpec the height requirements for this view 668a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param heightUsed extra space that has been used up by the parent 669a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * vertically (possibly by other children of the parent) 670a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 671a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public void onMeasureChild(View child, int parentWidthMeasureSpec, int widthUsed, 672a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int parentHeightMeasureSpec, int heightUsed) { 673a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell measureChildWithMargins(child, parentWidthMeasureSpec, widthUsed, 674a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell parentHeightMeasureSpec, heightUsed); 675a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 676a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 677a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 678a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 679a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell prepareChildren(); 680a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell ensurePreDrawListener(); 681a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 682a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int paddingLeft = getPaddingLeft(); 683a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int paddingTop = getPaddingTop(); 684a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int paddingRight = getPaddingRight(); 685a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int paddingBottom = getPaddingBottom(); 686a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int layoutDirection = ViewCompat.getLayoutDirection(this); 687a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final boolean isRtl = layoutDirection == ViewCompat.LAYOUT_DIRECTION_RTL; 688a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int widthMode = MeasureSpec.getMode(widthMeasureSpec); 689a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int widthSize = MeasureSpec.getSize(widthMeasureSpec); 69075284fffafacd32f4d178020050589f9e70e5ed9Chris Banes final int heightMode = MeasureSpec.getMode(heightMeasureSpec); 69175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes final int heightSize = MeasureSpec.getSize(heightMeasureSpec); 692a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 693a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int widthPadding = paddingLeft + paddingRight; 694a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int heightPadding = paddingTop + paddingBottom; 695a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int widthUsed = getSuggestedMinimumWidth(); 696a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int heightUsed = getSuggestedMinimumHeight(); 697a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int childState = 0; 698a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 69975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes final boolean applyInsets = mLastInsets != null && ViewCompat.getFitsSystemWindows(this); 70075284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 701a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childCount = mDependencySortedChildren.size(); 702a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int i = 0; i < childCount; i++) { 703a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final View child = mDependencySortedChildren.get(i); 704a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 705a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 706a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int keylineWidthUsed = 0; 707a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (lp.keyline >= 0 && widthMode != MeasureSpec.UNSPECIFIED) { 708a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int keylinePos = getKeyline(lp.keyline); 709a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int keylineGravity = GravityCompat.getAbsoluteGravity( 710a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell resolveKeylineGravity(lp.gravity), layoutDirection) 711a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell & Gravity.HORIZONTAL_GRAVITY_MASK; 712a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if ((keylineGravity == Gravity.LEFT && !isRtl) 713a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell || (keylineGravity == Gravity.RIGHT && isRtl)) { 714a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell keylineWidthUsed = Math.max(0, widthSize - paddingRight - keylinePos); 715a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else if ((keylineGravity == Gravity.RIGHT && !isRtl) 716a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell || (keylineGravity == Gravity.LEFT && isRtl)) { 717a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell keylineWidthUsed = Math.max(0, keylinePos - paddingLeft); 718a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 719a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 720a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 72175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes int childWidthMeasureSpec = widthMeasureSpec; 72275284fffafacd32f4d178020050589f9e70e5ed9Chris Banes int childHeightMeasureSpec = heightMeasureSpec; 72375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes if (applyInsets && !ViewCompat.getFitsSystemWindows(child)) { 72475284fffafacd32f4d178020050589f9e70e5ed9Chris Banes // We're set to handle insets but this child isn't, so we will measure the 72575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes // child as if there are no insets 72675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes final int horizInsets = mLastInsets.getSystemWindowInsetLeft() 72775284fffafacd32f4d178020050589f9e70e5ed9Chris Banes + mLastInsets.getSystemWindowInsetRight(); 72875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes final int vertInsets = mLastInsets.getSystemWindowInsetTop() 72975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes + mLastInsets.getSystemWindowInsetBottom(); 73075284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 73175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes childWidthMeasureSpec = MeasureSpec.makeMeasureSpec( 73275284fffafacd32f4d178020050589f9e70e5ed9Chris Banes widthSize - horizInsets, widthMode); 73375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes childHeightMeasureSpec = MeasureSpec.makeMeasureSpec( 73475284fffafacd32f4d178020050589f9e70e5ed9Chris Banes heightSize - vertInsets, heightMode); 73575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 73675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 737a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Behavior b = lp.getBehavior(); 73875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes if (b == null || !b.onMeasureChild(this, child, childWidthMeasureSpec, keylineWidthUsed, 73975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes childHeightMeasureSpec, 0)) { 74075284fffafacd32f4d178020050589f9e70e5ed9Chris Banes onMeasureChild(child, childWidthMeasureSpec, keylineWidthUsed, 74175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes childHeightMeasureSpec, 0); 742a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 743a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 744a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell widthUsed = Math.max(widthUsed, widthPadding + child.getMeasuredWidth() + 745a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell lp.leftMargin + lp.rightMargin); 746a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 747a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell heightUsed = Math.max(heightUsed, heightPadding + child.getMeasuredHeight() + 748a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell lp.topMargin + lp.bottomMargin); 749a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell childState = ViewCompat.combineMeasuredStates(childState, 750a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell ViewCompat.getMeasuredState(child)); 751a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 752a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 753a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int width = ViewCompat.resolveSizeAndState(widthUsed, widthMeasureSpec, 754a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell childState & ViewCompat.MEASURED_STATE_MASK); 755a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int height = ViewCompat.resolveSizeAndState(heightUsed, heightMeasureSpec, 756a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell childState << ViewCompat.MEASURED_HEIGHT_STATE_SHIFT); 757a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell setMeasuredDimension(width, height); 758a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 759a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 76017ed3263761329f6aa6796941358c41001fff325Chris Banes private WindowInsetsCompat dispatchApplyWindowInsetsToBehaviors(WindowInsetsCompat insets) { 76175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes if (insets.isConsumed()) { 76217ed3263761329f6aa6796941358c41001fff325Chris Banes return insets; 76375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 76475284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 76575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes for (int i = 0, z = getChildCount(); i < z; i++) { 76675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes final View child = getChildAt(i); 76775284fffafacd32f4d178020050589f9e70e5ed9Chris Banes if (ViewCompat.getFitsSystemWindows(child)) { 76875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 76975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes final Behavior b = lp.getBehavior(); 77075284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 77175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes if (b != null) { 77275284fffafacd32f4d178020050589f9e70e5ed9Chris Banes // If the view has a behavior, let it try first 77375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes insets = b.onApplyWindowInsets(this, child, insets); 77475284fffafacd32f4d178020050589f9e70e5ed9Chris Banes if (insets.isConsumed()) { 77575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes // If it consumed the insets, break 77675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes break; 77775284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 77875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 77975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 78075284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 78117ed3263761329f6aa6796941358c41001fff325Chris Banes 78217ed3263761329f6aa6796941358c41001fff325Chris Banes return insets; 78375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 78475284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 785a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 786a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Called to lay out each individual child view unless a 787a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link CoordinatorLayout.Behavior Behavior} is present. The Behavior may choose to 788a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * delegate child measurement to this method. 789a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 790a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child view to lay out 791a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param layoutDirection the resolved layout direction for the CoordinatorLayout, such as 792a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link ViewCompat#LAYOUT_DIRECTION_LTR} or 793a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link ViewCompat#LAYOUT_DIRECTION_RTL}. 794a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 795a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public void onLayoutChild(View child, int layoutDirection) { 796a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 797a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (lp.checkAnchorChanged()) { 798a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell throw new IllegalStateException("An anchor may not be changed after CoordinatorLayout" 799a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell + " measurement begins before layout is complete."); 800a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 801a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (lp.mAnchorView != null) { 802a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell layoutChildWithAnchor(child, lp.mAnchorView, layoutDirection); 803a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else if (lp.keyline >= 0) { 804a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell layoutChildWithKeyline(child, lp.keyline, layoutDirection); 805a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else { 806a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell layoutChild(child, layoutDirection); 807a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 808a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 809a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 810a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 811a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell protected void onLayout(boolean changed, int l, int t, int r, int b) { 812a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int layoutDirection = ViewCompat.getLayoutDirection(this); 813a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childCount = mDependencySortedChildren.size(); 814a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int i = 0; i < childCount; i++) { 815a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final View child = mDependencySortedChildren.get(i); 816a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 817a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Behavior behavior = lp.getBehavior(); 818a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 819a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (behavior == null || !behavior.onLayoutChild(this, child, layoutDirection)) { 820a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell onLayoutChild(child, layoutDirection); 821a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 822a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 823a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 824a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 82575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes @Override 82675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes public void onDraw(Canvas c) { 82775284fffafacd32f4d178020050589f9e70e5ed9Chris Banes super.onDraw(c); 82875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes if (mDrawStatusBarBackground && mStatusBarBackground != null) { 82975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes final int inset = mLastInsets != null ? mLastInsets.getSystemWindowInsetTop() : 0; 83075284fffafacd32f4d178020050589f9e70e5ed9Chris Banes if (inset > 0) { 83175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes mStatusBarBackground.setBounds(0, 0, getWidth(), inset); 83275284fffafacd32f4d178020050589f9e70e5ed9Chris Banes mStatusBarBackground.draw(c); 83375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 83475284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 83575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 83675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 837a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 838a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Mark the last known child position rect for the given child view. 839a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * This will be used when checking if a child view's position has changed between frames. 840a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * The rect used here should be one returned by 841a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link #getChildRect(android.view.View, boolean, android.graphics.Rect)}, with translation 842a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * disabled. 843a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 844a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child view to set for 845a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param r rect to set 846a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 847a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void recordLastChildRect(View child, Rect r) { 848a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 849a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell lp.setLastChildRect(r); 850a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 851a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 852a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 853a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Get the last known child rect recorded by 854a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link #recordLastChildRect(android.view.View, android.graphics.Rect)}. 855a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 856a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child view to retrieve from 857a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param out rect to set to the outpur values 858a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 859a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void getLastChildRect(View child, Rect out) { 860a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 861a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell out.set(lp.getLastChildRect()); 862a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 863a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 864a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 865a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Get the position rect for the given child. If the child has currently requested layout 866a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * or has a visibility of GONE. 867a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 868a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child view to check 869a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param transform true to include transformation in the output rect, false to 870a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * only account for the base position 871a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param out rect to set to the output values 872a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 873a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void getChildRect(View child, boolean transform, Rect out) { 874a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (child.isLayoutRequested() || child.getVisibility() == View.GONE) { 875a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell out.set(0, 0, 0, 0); 876a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return; 877a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 878a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (transform) { 879a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getDescendantRect(child, out); 880a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else { 881a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell out.set(child.getLeft(), child.getTop(), child.getRight(), child.getBottom()); 882a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 883a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 884a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 885a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 886a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Calculate the desired child rect relative to an anchor rect, respecting both 887a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * gravity and anchorGravity. 888a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 889a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child view to calculate a rect for 890a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param layoutDirection the desired layout direction for the CoordinatorLayout 891a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param anchorRect rect in CoordinatorLayout coordinates of the anchor view area 892a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param out rect to set to the output values 893a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 894a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void getDesiredAnchoredChildRect(View child, int layoutDirection, Rect anchorRect, Rect out) { 895a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 896a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int absGravity = GravityCompat.getAbsoluteGravity( 897a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell resolveAnchoredChildGravity(lp.gravity), layoutDirection); 898a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int absAnchorGravity = GravityCompat.getAbsoluteGravity( 899a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell resolveGravity(lp.anchorGravity), 900a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell layoutDirection); 901a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 902a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int hgrav = absGravity & Gravity.HORIZONTAL_GRAVITY_MASK; 903a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int vgrav = absGravity & Gravity.VERTICAL_GRAVITY_MASK; 904a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int anchorHgrav = absAnchorGravity & Gravity.HORIZONTAL_GRAVITY_MASK; 905a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int anchorVgrav = absAnchorGravity & Gravity.VERTICAL_GRAVITY_MASK; 906a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 907a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childWidth = child.getMeasuredWidth(); 908a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childHeight = child.getMeasuredHeight(); 909a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 910a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int left; 911a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int top; 912a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 913d09e24f8d4c10e72dee0e435d3289ddd10223aa0Adam Powell // Align to the anchor. This puts us in an assumed right/bottom child view gravity. 914d09e24f8d4c10e72dee0e435d3289ddd10223aa0Adam Powell // If this is not the case we will subtract out the appropriate portion of 915d09e24f8d4c10e72dee0e435d3289ddd10223aa0Adam Powell // the child size below. 916a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell switch (anchorHgrav) { 917a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell default: 918a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.LEFT: 919a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell left = anchorRect.left; 920a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 921a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.RIGHT: 922d09e24f8d4c10e72dee0e435d3289ddd10223aa0Adam Powell left = anchorRect.right; 923a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 924a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.CENTER_HORIZONTAL: 925d09e24f8d4c10e72dee0e435d3289ddd10223aa0Adam Powell left = anchorRect.left + anchorRect.width() / 2; 926a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 927a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 928a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 929a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell switch (anchorVgrav) { 930a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell default: 931a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.TOP: 932a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell top = anchorRect.top; 933a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 934a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.BOTTOM: 935d09e24f8d4c10e72dee0e435d3289ddd10223aa0Adam Powell top = anchorRect.bottom; 936a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 937a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.CENTER_VERTICAL: 938d09e24f8d4c10e72dee0e435d3289ddd10223aa0Adam Powell top = anchorRect.top + anchorRect.height() / 2; 939a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 940a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 941a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 942d09e24f8d4c10e72dee0e435d3289ddd10223aa0Adam Powell // Offset by the child view's gravity itself. The above assumed right/bottom gravity. 943a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell switch (hgrav) { 944a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell default: 945a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.LEFT: 946d09e24f8d4c10e72dee0e435d3289ddd10223aa0Adam Powell left -= childWidth; 947a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 948a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.RIGHT: 949d09e24f8d4c10e72dee0e435d3289ddd10223aa0Adam Powell // Do nothing, we're already in position. 950a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 951a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.CENTER_HORIZONTAL: 952d09e24f8d4c10e72dee0e435d3289ddd10223aa0Adam Powell left -= childWidth / 2; 953a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 954a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 955a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 956a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell switch (vgrav) { 957a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell default: 958a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.TOP: 959d09e24f8d4c10e72dee0e435d3289ddd10223aa0Adam Powell top -= childHeight; 960a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 961a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.BOTTOM: 962d09e24f8d4c10e72dee0e435d3289ddd10223aa0Adam Powell // Do nothing, we're already in position. 963a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 964a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.CENTER_VERTICAL: 965d09e24f8d4c10e72dee0e435d3289ddd10223aa0Adam Powell top -= childHeight / 2; 966a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 967a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 968a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 969a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int width = getWidth(); 970a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int height = getHeight(); 971a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 972a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Obey margins and padding 973a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell left = Math.max(getPaddingLeft() + lp.leftMargin, 974a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Math.min(left, 975a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell width - getPaddingRight() - childWidth - lp.rightMargin)); 976a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell top = Math.max(getPaddingTop() + lp.topMargin, 977a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Math.min(top, 978a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell height - getPaddingBottom() - childHeight - lp.bottomMargin)); 979a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 980a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell out.set(left, top, left + childWidth, top + childHeight); 981a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 982a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 983a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 984a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * CORE ASSUMPTION: anchor has been laid out by the time this is called for a given child view. 985a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 986a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child to lay out 987a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param anchor view to anchor child relative to; already laid out. 988a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param layoutDirection ViewCompat constant for layout direction 989a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 990a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private void layoutChildWithAnchor(View child, View anchor, int layoutDirection) { 991a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 992a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 993a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Rect anchorRect = mTempRect1; 994a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Rect childRect = mTempRect2; 995a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getDescendantRect(anchor, anchorRect); 996a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getDesiredAnchoredChildRect(child, layoutDirection, anchorRect, childRect); 997a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 998a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell child.layout(childRect.left, childRect.top, childRect.right, childRect.bottom); 999a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1000a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1001a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1002a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Lay out a child view with respect to a keyline. 1003a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1004a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>The keyline represents a horizontal offset from the unpadded starting edge of 1005a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * the CoordinatorLayout. The child's gravity will affect how it is positioned with 1006a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * respect to the keyline.</p> 1007a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1008a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child to lay out 1009a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param keyline offset from the starting edge in pixels of the keyline to align with 1010a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param layoutDirection ViewCompat constant for layout direction 1011a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1012a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private void layoutChildWithKeyline(View child, int keyline, int layoutDirection) { 1013a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 1014a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int absGravity = GravityCompat.getAbsoluteGravity( 1015a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell resolveKeylineGravity(lp.gravity), layoutDirection); 1016a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1017a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int hgrav = absGravity & Gravity.HORIZONTAL_GRAVITY_MASK; 1018a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int vgrav = absGravity & Gravity.VERTICAL_GRAVITY_MASK; 1019a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int width = getWidth(); 1020a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int height = getHeight(); 1021a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childWidth = child.getMeasuredWidth(); 1022a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childHeight = child.getMeasuredHeight(); 1023a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1024a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (layoutDirection == ViewCompat.LAYOUT_DIRECTION_RTL) { 1025a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell keyline = width - keyline; 1026a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1027a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1028a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int left = getKeyline(keyline) - childWidth; 1029a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int top = 0; 1030a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1031a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell switch (hgrav) { 1032a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell default: 1033a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.LEFT: 1034a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Nothing to do. 1035a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 1036a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.RIGHT: 1037a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell left += childWidth; 1038a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 1039a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.CENTER_HORIZONTAL: 1040a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell left += childWidth / 2; 1041a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 1042a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1043a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1044a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell switch (vgrav) { 1045a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell default: 1046a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.TOP: 1047a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Do nothing, we're already in position. 1048a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 1049a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.BOTTOM: 1050a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell top += childHeight; 1051a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 1052a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.CENTER_VERTICAL: 1053a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell top += childHeight / 2; 1054a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 1055a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1056a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1057a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Obey margins and padding 1058a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell left = Math.max(getPaddingLeft() + lp.leftMargin, 1059a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Math.min(left, 1060a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell width - getPaddingRight() - childWidth - lp.rightMargin)); 1061a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell top = Math.max(getPaddingTop() + lp.topMargin, 1062a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Math.min(top, 1063a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell height - getPaddingBottom() - childHeight - lp.bottomMargin)); 1064a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1065a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell child.layout(left, top, left + childWidth, top + childHeight); 1066a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1067a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1068a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1069a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Lay out a child view with no special handling. This will position the child as 1070a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * if it were within a FrameLayout or similar simple frame. 1071a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1072a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child view to lay out 1073a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param layoutDirection ViewCompat constant for the desired layout direction 1074a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1075a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private void layoutChild(View child, int layoutDirection) { 1076a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 1077a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Rect parent = mTempRect1; 1078a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell parent.set(getPaddingLeft() + lp.leftMargin, 1079a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getPaddingTop() + lp.topMargin, 1080a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getWidth() - getPaddingRight() - lp.rightMargin, 1081a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getHeight() - getPaddingBottom() - lp.bottomMargin); 108275284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 108375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes if (mLastInsets != null && ViewCompat.getFitsSystemWindows(this) 108475284fffafacd32f4d178020050589f9e70e5ed9Chris Banes && !ViewCompat.getFitsSystemWindows(child)) { 108575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes // If we're set to handle insets but this child isn't, then it has been measured as 108675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes // if there are no insets. We need to lay it out to match. 108775284fffafacd32f4d178020050589f9e70e5ed9Chris Banes parent.left += mLastInsets.getSystemWindowInsetLeft(); 108875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes parent.top += mLastInsets.getSystemWindowInsetTop(); 108975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes parent.right -= mLastInsets.getSystemWindowInsetRight(); 109075284fffafacd32f4d178020050589f9e70e5ed9Chris Banes parent.bottom -= mLastInsets.getSystemWindowInsetBottom(); 109175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 109275284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 1093a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Rect out = mTempRect2; 1094a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell GravityCompat.apply(resolveGravity(lp.gravity), child.getMeasuredWidth(), 1095a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell child.getMeasuredHeight(), parent, out, layoutDirection); 1096a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell child.layout(out.left, out.top, out.right, out.bottom); 1097a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1098a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1099a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1100a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Return the given gravity value or the default if the passed value is NO_GRAVITY. 1101a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * This should be used for children that are not anchored to another view or a keyline. 1102a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1103a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private static int resolveGravity(int gravity) { 1104a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return gravity == Gravity.NO_GRAVITY ? GravityCompat.START | Gravity.TOP : gravity; 1105a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1106a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1107a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1108a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Return the given gravity value or the default if the passed value is NO_GRAVITY. 1109a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * This should be used for children that are positioned relative to a keyline. 1110a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1111a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private static int resolveKeylineGravity(int gravity) { 1112a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return gravity == Gravity.NO_GRAVITY ? GravityCompat.END | Gravity.TOP : gravity; 1113a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1114a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1115a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1116a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Return the given gravity value or the default if the passed value is NO_GRAVITY. 1117a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * This should be used for children that are anchored to another view. 1118a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1119a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private static int resolveAnchoredChildGravity(int gravity) { 1120a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return gravity == Gravity.NO_GRAVITY ? Gravity.CENTER : gravity; 1121a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1122a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1123a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 1124a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell protected boolean drawChild(Canvas canvas, View child, long drawingTime) { 1125a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 1126a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (lp.mBehavior != null && lp.mBehavior.getScrimOpacity(this, child) > 0.f) { 1127a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mScrimPaint == null) { 1128a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mScrimPaint = new Paint(); 1129a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1130a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mScrimPaint.setColor(lp.mBehavior.getScrimColor(this, child)); 1131a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1132a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // TODO: Set the clip appropriately to avoid unnecessary overdraw. 1133a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell canvas.drawRect(getPaddingLeft(), getPaddingTop(), 1134a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getWidth() - getPaddingRight(), getHeight() - getPaddingBottom(), mScrimPaint); 1135a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1136a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return super.drawChild(canvas, child, drawingTime); 1137a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1138a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1139a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1140a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * Dispatch any dependent view changes to the relevant {@link Behavior} instances. 1141a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * 1142a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * Usually run as part of the pre-draw step when at least one child view has a reported 1143a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * dependency on another view. This allows CoordinatorLayout to account for layout 1144a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * changes and animations that occur outside of the normal layout pass. 1145a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1146a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * It can also be ran as part of the nested scrolling dispatch to ensure that any offsetting 1147a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * is completed within the correct coordinate window. 1148a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * 1149a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * The offsetting behavior implemented here does not store the computed offset in 1150a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * the LayoutParams; instead it expects that the layout process will always reconstruct 1151a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * the proper positioning. 1152a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * 1153a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * @param fromNestedScroll true if this is being called from one of the nested scroll methods, 1154a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * false if run as part of the pre-draw step. 1155a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1156a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes void dispatchOnDependentViewChanged(final boolean fromNestedScroll) { 1157a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int layoutDirection = ViewCompat.getLayoutDirection(this); 1158a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childCount = mDependencySortedChildren.size(); 1159a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int i = 0; i < childCount; i++) { 1160a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final View child = mDependencySortedChildren.get(i); 1161a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 1162a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1163a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Check child views before for anchor 1164a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int j = 0; j < i; j++) { 1165a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final View checkChild = mDependencySortedChildren.get(j); 1166a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1167a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (lp.mAnchorDirectChild == checkChild) { 1168a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell offsetChildToAnchor(child, layoutDirection); 1169a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1170a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1171a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1172a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Did it change? if not continue 1173a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Rect oldRect = mTempRect1; 1174a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Rect newRect = mTempRect2; 1175a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getLastChildRect(child, oldRect); 1176b7f9224b1495db47eb8fd813b5912250e900770aChris Banes getChildRect(child, true, newRect); 1177a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (oldRect.equals(newRect)) { 1178a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell continue; 1179a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1180a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell recordLastChildRect(child, newRect); 1181a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1182a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Update any behavior-dependent views for the change 1183a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int j = i + 1; j < childCount; j++) { 1184a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final View checkChild = mDependencySortedChildren.get(j); 1185a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams checkLp = (LayoutParams) checkChild.getLayoutParams(); 1186a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Behavior b = checkLp.getBehavior(); 1187a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1188a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (b != null && b.layoutDependsOn(this, checkChild, child)) { 1189a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes if (!fromNestedScroll && checkLp.getChangedAfterNestedScroll()) { 1190a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes // If this is not from a nested scroll and we have already been changed 1191a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes // from a nested scroll, skip the dispatch and reset the flag 1192a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes checkLp.resetChangedAfterNestedScroll(); 1193a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes continue; 1194a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1195a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 1196a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes final boolean handled = b.onDependentViewChanged(this, checkChild, child); 1197a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 1198a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes if (fromNestedScroll) { 1199a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes // If this is from a nested scroll, set the flag so that we may skip 1200a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes // any resulting onPreDraw dispatch (if needed) 1201a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes checkLp.setChangedAfterNestedScroll(handled); 1202a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1203a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1204a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1205a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1206a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1207a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 12088248a6287c4ff9fa71ff6760bb6fe0906f0d6607Chris Banes void dispatchDependentViewRemoved(View view) { 12098248a6287c4ff9fa71ff6760bb6fe0906f0d6607Chris Banes final int childCount = mDependencySortedChildren.size(); 12108248a6287c4ff9fa71ff6760bb6fe0906f0d6607Chris Banes boolean viewSeen = false; 12110b00489086b22c9688c8c04990dadf54489d45e3Chris Banes for (int i = 0; i < childCount; i++) { 12128248a6287c4ff9fa71ff6760bb6fe0906f0d6607Chris Banes final View child = mDependencySortedChildren.get(i); 12138248a6287c4ff9fa71ff6760bb6fe0906f0d6607Chris Banes if (child == view) { 12148248a6287c4ff9fa71ff6760bb6fe0906f0d6607Chris Banes // We've seen our view, which means that any Views after this could be dependent 12158248a6287c4ff9fa71ff6760bb6fe0906f0d6607Chris Banes viewSeen = true; 12168248a6287c4ff9fa71ff6760bb6fe0906f0d6607Chris Banes continue; 12178248a6287c4ff9fa71ff6760bb6fe0906f0d6607Chris Banes } 12188248a6287c4ff9fa71ff6760bb6fe0906f0d6607Chris Banes if (viewSeen) { 12198248a6287c4ff9fa71ff6760bb6fe0906f0d6607Chris Banes CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams) 12208248a6287c4ff9fa71ff6760bb6fe0906f0d6607Chris Banes child.getLayoutParams(); 12218248a6287c4ff9fa71ff6760bb6fe0906f0d6607Chris Banes CoordinatorLayout.Behavior b = lp.getBehavior(); 12228248a6287c4ff9fa71ff6760bb6fe0906f0d6607Chris Banes if (b != null && lp.dependsOn(this, child, view)) { 12238248a6287c4ff9fa71ff6760bb6fe0906f0d6607Chris Banes b.onDependentViewRemoved(this, child, view); 12248248a6287c4ff9fa71ff6760bb6fe0906f0d6607Chris Banes } 12250b00489086b22c9688c8c04990dadf54489d45e3Chris Banes } 12260b00489086b22c9688c8c04990dadf54489d45e3Chris Banes } 12270b00489086b22c9688c8c04990dadf54489d45e3Chris Banes } 12280b00489086b22c9688c8c04990dadf54489d45e3Chris Banes 1229a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes /** 1230a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * Allows the caller to manually dispatch 1231a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * {@link Behavior#onDependentViewChanged(CoordinatorLayout, View, View)} to the associated 1232a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * {@link Behavior} instances of views which depend on the provided {@link View}. 1233a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * 1234a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * <p>You should not normally need to call this method as the it will be automatically done 1235a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * when the view has changed. 1236a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * 1237a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * @param view the View to find dependents of to dispatch the call. 1238a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes */ 1239a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes public void dispatchDependentViewsChanged(View view) { 1240a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes final int childCount = mDependencySortedChildren.size(); 1241a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes boolean viewSeen = false; 1242a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes for (int i = 0; i < childCount; i++) { 1243a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes final View child = mDependencySortedChildren.get(i); 1244a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes if (child == view) { 1245a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes // We've seen our view, which means that any Views after this could be dependent 1246a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes viewSeen = true; 1247a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes continue; 1248a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1249a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes if (viewSeen) { 1250a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams) 1251a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes child.getLayoutParams(); 1252a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes CoordinatorLayout.Behavior b = lp.getBehavior(); 1253a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes if (b != null && lp.dependsOn(this, child, view)) { 1254a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes b.onDependentViewChanged(this, child, view); 1255a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1256a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1257a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1258a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1259a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1260a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1261a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * Returns the list of views which the provided view depends on. Do not store this list as it's 1262a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * contents may not be valid beyond the caller. 1263a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * 1264a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * @param child the view to find dependencies for. 1265a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * 1266a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * @return the list of views which {@code child} depends on. 1267a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes */ 1268a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes public List<View> getDependencies(View child) { 1269a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes // TODO The result of this is probably a good candidate for caching 1270a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 1271a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 1272a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes final List<View> list = mTempDependenciesList; 1273a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes list.clear(); 1274a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 1275a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes final int childCount = getChildCount(); 1276a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes for (int i = 0; i < childCount; i++) { 1277a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes final View other = getChildAt(i); 1278a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes if (other == child) { 1279a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes continue; 1280a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1281a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes if (lp.dependsOn(this, child, other)) { 1282a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes list.add(other); 1283a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1284a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1285a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 1286a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes return list; 1287a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1288a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 1289a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes /** 1290a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Add or remove the pre-draw listener as necessary. 1291a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1292a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void ensurePreDrawListener() { 1293a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean hasDependencies = false; 1294a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childCount = getChildCount(); 1295a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int i = 0; i < childCount; i++) { 1296a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final View child = getChildAt(i); 1297a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (hasDependencies(child)) { 1298a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell hasDependencies = true; 1299a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 1300a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1301a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1302a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1303a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (hasDependencies != mNeedsPreDrawListener) { 1304a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (hasDependencies) { 1305a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell addPreDrawListener(); 1306a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else { 1307a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell removePreDrawListener(); 1308a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1309a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1310a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1311a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1312a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1313a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Check if the given child has any layout dependencies on other child views. 1314a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1315a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean hasDependencies(View child) { 1316a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 1317a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (lp.mAnchorView != null) { 1318a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return true; 1319a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1320a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1321a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childCount = getChildCount(); 1322a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int i = 0; i < childCount; i++) { 1323a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final View other = getChildAt(i); 1324a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (other == child) { 1325a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell continue; 1326a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1327a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (lp.dependsOn(this, child, other)) { 1328a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return true; 1329a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1330a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1331a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return false; 1332a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1333a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1334a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1335a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Add the pre-draw listener if we're attached to a window and mark that we currently 1336a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * need it when attached. 1337a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1338a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void addPreDrawListener() { 1339a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mIsAttachedToWindow) { 1340a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Add the listener 1341a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mOnPreDrawListener == null) { 1342a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mOnPreDrawListener = new OnPreDrawListener(); 1343a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1344a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final ViewTreeObserver vto = getViewTreeObserver(); 1345a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell vto.addOnPreDrawListener(mOnPreDrawListener); 1346a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1347a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1348a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Record that we need the listener regardless of whether or not we're attached. 1349a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // We'll add the real listener when we become attached. 1350a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mNeedsPreDrawListener = true; 1351a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1352a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1353a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1354a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Remove the pre-draw listener if we're attached to a window and mark that we currently 1355a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * do not need it when attached. 1356a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1357a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void removePreDrawListener() { 1358a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mIsAttachedToWindow) { 1359a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mOnPreDrawListener != null) { 1360a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final ViewTreeObserver vto = getViewTreeObserver(); 1361a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell vto.removeOnPreDrawListener(mOnPreDrawListener); 1362a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1363a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1364a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mNeedsPreDrawListener = false; 1365a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1366a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1367a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1368a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Adjust the child left, top, right, bottom rect to the correct anchor view position, 1369a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * respecting gravity and anchor gravity. 1370a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1371a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Note that child translation properties are ignored in this process, allowing children 1372a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * to be animated away from their anchor. However, if the anchor view is animated, 1373a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * the child will be offset to match the anchor's translated position. 1374a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1375a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void offsetChildToAnchor(View child, int layoutDirection) { 1376a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 1377a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (lp.mAnchorView != null) { 1378a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Rect anchorRect = mTempRect1; 1379a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Rect childRect = mTempRect2; 1380a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Rect desiredChildRect = mTempRect3; 1381a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1382a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getDescendantRect(lp.mAnchorView, anchorRect); 1383a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getChildRect(child, false, childRect); 1384a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getDesiredAnchoredChildRect(child, layoutDirection, anchorRect, desiredChildRect); 1385a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1386a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int dx = desiredChildRect.left - childRect.left; 1387a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int dy = desiredChildRect.top - childRect.top; 1388a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1389a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (dx != 0) { 1390a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell child.offsetLeftAndRight(dx); 1391a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1392a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (dy != 0) { 1393a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell child.offsetTopAndBottom(dy); 1394a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1395a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 1396a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes if (dx != 0 || dy != 0) { 1397a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes // If we have needed to move, make sure to notify the child's Behavior 1398a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes final Behavior b = lp.getBehavior(); 1399a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes if (b != null) { 1400a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes b.onDependentViewChanged(this, child, lp.mAnchorView); 1401a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1402a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1403a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1404a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1405a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1406a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1407a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Check if a given point in the CoordinatorLayout's coordinates are within the view bounds 1408a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * of the given direct child view. 1409a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1410a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child view to test 1411a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param x X coordinate to test, in the CoordinatorLayout's coordinate system 1412a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param y Y coordinate to test, in the CoordinatorLayout's coordinate system 1413a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true if the point is within the child view's bounds, false otherwise 1414a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1415a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean isPointInChildBounds(View child, int x, int y) { 1416a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Rect r = mTempRect1; 1417a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getDescendantRect(child, r); 1418a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return r.contains(x, y); 1419a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1420a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1421b7f9224b1495db47eb8fd813b5912250e900770aChris Banes /** 1422b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * Check whether two views overlap each other. The views need to be descendants of this 1423b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * {@link CoordinatorLayout} in the view hierarchy. 1424b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * 1425b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * @param first first child view to test 1426b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * @param second second child view to test 1427b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * @return true if both views are visible and overlap each other 1428b7f9224b1495db47eb8fd813b5912250e900770aChris Banes */ 1429b7f9224b1495db47eb8fd813b5912250e900770aChris Banes public boolean doViewsOverlap(View first, View second) { 1430b7f9224b1495db47eb8fd813b5912250e900770aChris Banes if (first.getVisibility() == VISIBLE && second.getVisibility() == VISIBLE) { 1431b7f9224b1495db47eb8fd813b5912250e900770aChris Banes final Rect firstRect = mTempRect1; 1432b7f9224b1495db47eb8fd813b5912250e900770aChris Banes getChildRect(first, first.getParent() != this, firstRect); 1433b7f9224b1495db47eb8fd813b5912250e900770aChris Banes final Rect secondRect = mTempRect2; 1434b7f9224b1495db47eb8fd813b5912250e900770aChris Banes getChildRect(second, second.getParent() != this, secondRect); 1435b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 1436b7f9224b1495db47eb8fd813b5912250e900770aChris Banes return !(firstRect.left > secondRect.right || firstRect.top > secondRect.bottom 1437b7f9224b1495db47eb8fd813b5912250e900770aChris Banes || firstRect.right < secondRect.left || firstRect.bottom < secondRect.top); 1438b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 1439b7f9224b1495db47eb8fd813b5912250e900770aChris Banes return false; 1440b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 1441b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 1442a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 1443a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public LayoutParams generateLayoutParams(AttributeSet attrs) { 1444a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return new LayoutParams(getContext(), attrs); 1445a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1446a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1447a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 1448a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { 1449a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (p instanceof LayoutParams) { 1450a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return new LayoutParams((LayoutParams) p); 1451a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else if (p instanceof MarginLayoutParams) { 1452a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return new LayoutParams((MarginLayoutParams) p); 1453a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1454a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return new LayoutParams(p); 1455a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1456a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1457a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 1458a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell protected LayoutParams generateDefaultLayoutParams() { 1459a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); 1460a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1461a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1462a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 1463a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { 1464a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return p instanceof LayoutParams && super.checkLayoutParams(p); 1465a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1466a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1467a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) { 14685cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell boolean handled = false; 14695cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 14705cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final int childCount = getChildCount(); 14715cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell for (int i = 0; i < childCount; i++) { 14725cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final View view = getChildAt(i); 14735cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final LayoutParams lp = (LayoutParams) view.getLayoutParams(); 14745cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final Behavior viewBehavior = lp.getBehavior(); 14755cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (viewBehavior != null) { 14765cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final boolean accepted = viewBehavior.onStartNestedScroll(this, view, child, target, 14775cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell nestedScrollAxes); 14785cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell handled |= accepted; 14795cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 14805cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell lp.acceptNestedScroll(accepted); 14815cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } else { 14825cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell lp.acceptNestedScroll(false); 14835cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 14845cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 14855cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell return handled; 1486a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1487a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1488a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public void onNestedScrollAccepted(View child, View target, int nestedScrollAxes) { 1489a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mNestedScrollingParentHelper.onNestedScrollAccepted(child, target, nestedScrollAxes); 14905cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell mNestedScrollingDirectChild = child; 14915cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell mNestedScrollingTarget = target; 14925cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 14935cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final int childCount = getChildCount(); 14945cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell for (int i = 0; i < childCount; i++) { 14955cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final View view = getChildAt(i); 14965cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final LayoutParams lp = (LayoutParams) view.getLayoutParams(); 14975cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (!lp.isNestedScrollAccepted()) { 14985cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell continue; 14995cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 15005cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 15015cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final Behavior viewBehavior = lp.getBehavior(); 15025cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (viewBehavior != null) { 15035cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell viewBehavior.onNestedScrollAccepted(this, view, child, target, nestedScrollAxes); 15045cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 15055cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 1506a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1507a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1508a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public void onStopNestedScroll(View target) { 1509a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mNestedScrollingParentHelper.onStopNestedScroll(target); 15105cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 15115cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final int childCount = getChildCount(); 15125cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell for (int i = 0; i < childCount; i++) { 15135cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final View view = getChildAt(i); 15145cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final LayoutParams lp = (LayoutParams) view.getLayoutParams(); 15155cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (!lp.isNestedScrollAccepted()) { 15165cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell continue; 15175cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 15185cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 15195cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final Behavior viewBehavior = lp.getBehavior(); 15205cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (viewBehavior != null) { 15215cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell viewBehavior.onStopNestedScroll(this, view, target); 15225cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 15235cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell lp.resetNestedScroll(); 1524a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes lp.resetChangedAfterNestedScroll(); 15255cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 15265cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 15275cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell mNestedScrollingDirectChild = null; 15285cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell mNestedScrollingTarget = null; 1529a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1530a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1531a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public void onNestedScroll(View target, int dxConsumed, int dyConsumed, 1532a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int dxUnconsumed, int dyUnconsumed) { 15335cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final int childCount = getChildCount(); 1534a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes boolean accepted = false; 1535a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 15365cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell for (int i = 0; i < childCount; i++) { 15375cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final View view = getChildAt(i); 15385cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final LayoutParams lp = (LayoutParams) view.getLayoutParams(); 15395cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (!lp.isNestedScrollAccepted()) { 15405cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell continue; 15415cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 15425cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 15435cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final Behavior viewBehavior = lp.getBehavior(); 15445cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (viewBehavior != null) { 15455cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell viewBehavior.onNestedScroll(this, view, target, dxConsumed, dyConsumed, 15465cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell dxUnconsumed, dyUnconsumed); 1547a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes accepted = true; 15485cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 15495cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 1550a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 1551a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes if (accepted) { 1552a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes dispatchOnDependentViewChanged(true); 1553a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1554a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1555a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1556a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) { 15575cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell int xConsumed = 0; 15585cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell int yConsumed = 0; 1559a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes boolean accepted = false; 15605cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 15615cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final int childCount = getChildCount(); 15625cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell for (int i = 0; i < childCount; i++) { 15635cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final View view = getChildAt(i); 15645cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final LayoutParams lp = (LayoutParams) view.getLayoutParams(); 15655cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (!lp.isNestedScrollAccepted()) { 15665cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell continue; 15675cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 15685cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 15695cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final Behavior viewBehavior = lp.getBehavior(); 15705cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (viewBehavior != null) { 15715cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell mTempIntPair[0] = mTempIntPair[1] = 0; 15725cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell viewBehavior.onNestedPreScroll(this, view, target, dx, dy, mTempIntPair); 15735cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 15745cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell xConsumed = dx > 0 ? Math.max(xConsumed, mTempIntPair[0]) 15755cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell : Math.min(xConsumed, mTempIntPair[0]); 15765cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell yConsumed = dy > 0 ? Math.max(yConsumed, mTempIntPair[1]) 15775cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell : Math.min(yConsumed, mTempIntPair[1]); 1578a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 1579a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes accepted = true; 15805cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 15815cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 15825cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 15835cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell consumed[0] = xConsumed; 15845cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell consumed[1] = yConsumed; 1585a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 1586a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes if (accepted) { 1587a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes dispatchOnDependentViewChanged(true); 1588a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1589a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1590a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1591a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) { 15925cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell boolean handled = false; 15935cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 15945cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final int childCount = getChildCount(); 15955cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell for (int i = 0; i < childCount; i++) { 15965cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final View view = getChildAt(i); 15975cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final LayoutParams lp = (LayoutParams) view.getLayoutParams(); 15985cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (!lp.isNestedScrollAccepted()) { 15995cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell continue; 16005cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 16015cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 16025cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final Behavior viewBehavior = lp.getBehavior(); 16035cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (viewBehavior != null) { 16045cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell handled |= viewBehavior.onNestedFling(this, view, target, velocityX, velocityY, 16055cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell consumed); 16065cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 16075cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 1608a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes if (handled) { 1609a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes dispatchOnDependentViewChanged(true); 1610a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 16115cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell return handled; 1612a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1613a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1614a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean onNestedPreFling(View target, float velocityX, float velocityY) { 16155cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell boolean handled = false; 16165cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 16175cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final int childCount = getChildCount(); 16185cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell for (int i = 0; i < childCount; i++) { 16195cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final View view = getChildAt(i); 16205cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final LayoutParams lp = (LayoutParams) view.getLayoutParams(); 16215cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (!lp.isNestedScrollAccepted()) { 16225cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell continue; 16235cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 16245cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 16255cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final Behavior viewBehavior = lp.getBehavior(); 16265cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (viewBehavior != null) { 16275cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell handled |= viewBehavior.onNestedPreFling(this, view, target, velocityX, velocityY); 16285cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 16295cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 16305cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell return handled; 1631a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1632a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1633a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public int getNestedScrollAxes() { 1634a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return mNestedScrollingParentHelper.getNestedScrollAxes(); 1635a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1636a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1637a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell class OnPreDrawListener implements ViewTreeObserver.OnPreDrawListener { 1638a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 1639a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean onPreDraw() { 1640a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes dispatchOnDependentViewChanged(false); 1641a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return true; 1642a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1643a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1644a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1645a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1646a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Sorts child views with higher Z values to the beginning of a collection. 1647a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1648a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell static class ViewElevationComparator implements Comparator<View> { 1649a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 1650a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public int compare(View lhs, View rhs) { 1651a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final float lz = ViewCompat.getZ(lhs); 1652a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final float rz = ViewCompat.getZ(rhs); 1653a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (lz > rz) { 1654a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return -1; 1655a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else if (lz < rz) { 1656a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return 1; 1657a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1658a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return 0; 1659a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1660a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1661a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1662a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1663a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Defines the default {@link Behavior} of a {@link View} class. 1664a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1665a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>When writing a custom view, use this annotation to define the default behavior 1666a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * when used as a direct child of an {@link CoordinatorLayout}. The default behavior 1667a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * can be overridden using {@link LayoutParams#setBehavior}.</p> 1668a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1669a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>Example: <code>@DefaultBehavior(MyBehavior.class)</code></p> 1670a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1671a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Retention(RetentionPolicy.RUNTIME) 1672a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public @interface DefaultBehavior { 1673a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Class<? extends Behavior> value(); 1674a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1675a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1676a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1677a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Interaction behavior plugin for child views of {@link CoordinatorLayout}. 1678a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1679a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>A Behavior implements one or more interactions that a user can take on a child view. 1680a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * These interactions may include drags, swipes, flings, or any other gestures.</p> 1681a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1682a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param <V> The View type that this Behavior operates on 1683a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1684a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public static abstract class Behavior<V extends View> { 1685a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1686a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1687a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Default constructor for instantiating Behaviors. 1688a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1689a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public Behavior() { 1690a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1691a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1692a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1693a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Default constructor for inflating Behaviors from layout. The Behavior will have 1694a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * the opportunity to parse specially defined layout parameters. These parameters will 1695a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * appear on the child view tag. 1696a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1697a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param context 1698a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param attrs 1699a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1700a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public Behavior(Context context, AttributeSet attrs) { 1701a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1702a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1703a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1704a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Respond to CoordinatorLayout touch events before they are dispatched to child views. 1705a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1706a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>Behaviors can use this to monitor inbound touch events until one decides to 1707a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * intercept the rest of the event stream to take an action on its associated child view. 1708a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * This method will return false until it detects the proper intercept conditions, then 1709a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * return true once those conditions have occurred.</p> 1710a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1711a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>Once a Behavior intercepts touch events, the rest of the event stream will 1712a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * be sent to the {@link #onTouchEvent} method.</p> 1713a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1714a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>The default implementation of this method always returns false.</p> 1715a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1716a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent view currently receiving this touch event 1717a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child view associated with this Behavior 1718a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param ev the MotionEvent describing the touch event being processed 1719a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true if this Behavior would like to intercept and take over the event stream. 1720a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * The default always returns false. 1721a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1722a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean onInterceptTouchEvent(CoordinatorLayout parent, V child, MotionEvent ev) { 1723a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return false; 1724a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1725a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1726a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1727a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Respond to CoordinatorLayout touch events after this Behavior has started 1728a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link #onInterceptTouchEvent intercepting} them. 1729a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1730a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>Behaviors may intercept touch events in order to help the CoordinatorLayout 1731a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * manipulate its child views. For example, a Behavior may allow a user to drag a 1732a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * UI pane open or closed. This method should perform actual mutations of view 1733a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * layout state.</p> 1734a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1735a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent view currently receiving this touch event 1736a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child view associated with this Behavior 1737a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param ev the MotionEvent describing the touch event being processed 1738a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true if this Behavior handled this touch event and would like to continue 1739a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * receiving events in this stream. The default always returns false. 1740a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1741a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean onTouchEvent(CoordinatorLayout parent, V child, MotionEvent ev) { 1742a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return false; 1743a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1744a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1745a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1746a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Supply a scrim color that will be painted behind the associated child view. 1747a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1748a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>A scrim may be used to indicate that the other elements beneath it are not currently 1749a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * interactive or actionable, drawing user focus and attention to the views above the scrim. 1750a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * </p> 1751a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1752a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>The default implementation returns {@link Color#BLACK}.</p> 1753a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1754a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent view of the given child 1755a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child view above the scrim 1756a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return the desired scrim color in 0xAARRGGBB format. The default return value is 1757a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link Color#BLACK}. 1758a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @see #getScrimOpacity(CoordinatorLayout, android.view.View) 1759a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 17604d4b8a2a5b5907383e7ca168dd01c76dc75ab930Adam Powell public int getScrimColor(CoordinatorLayout parent, V child) { 1761a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return Color.BLACK; 1762a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1763a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1764a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1765a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Determine the current opacity of the scrim behind a given child view 1766a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1767a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>A scrim may be used to indicate that the other elements beneath it are not currently 1768a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * interactive or actionable, drawing user focus and attention to the views above the scrim. 1769a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * </p> 1770a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1771a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>The default implementation returns 0.0f.</p> 1772a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1773a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent view of the given child 1774a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child view above the scrim 1775a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return the desired scrim opacity from 0.0f to 1.0f. The default return value is 0.0f. 1776a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 17774d4b8a2a5b5907383e7ca168dd01c76dc75ab930Adam Powell public float getScrimOpacity(CoordinatorLayout parent, V child) { 1778a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return 0.f; 1779a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1780a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1781a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1782a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Determine whether interaction with views behind the given child in the child order 1783a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * should be blocked. 1784a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1785a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>The default implementation returns true if 1786a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link #getScrimOpacity(CoordinatorLayout, android.view.View)} would return > 0.0f.</p> 1787a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1788a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent view of the given child 1789a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child view to test 1790a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true if {@link #getScrimOpacity(CoordinatorLayout, android.view.View)} would 1791a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * return > 0.0f. 1792a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1793a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean blocksInteractionBelow(CoordinatorLayout parent, V child) { 1794a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return getScrimOpacity(parent, child) > 0.f; 1795a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1796a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1797a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1798a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Determine whether the supplied child view has another specific sibling view as a 1799a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * layout dependency. 1800a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1801a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>This method will be called at least once in response to a layout request. If it 1802a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * returns true for a given child and dependency view pair, the parent CoordinatorLayout 1803a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * will:</p> 1804a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <ol> 1805a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <li>Always lay out this child after the dependent child is laid out, regardless 1806a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * of child order.</li> 1807a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <li>Call {@link #onDependentViewChanged} when the dependency view's layout or 1808a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * position changes.</li> 1809a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * </ol> 1810a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1811a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent view of the given child 1812a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child view to test 1813a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param dependency the proposed dependency of child 1814a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true if child's layout depends on the proposed dependency's layout, 1815a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * false otherwise 1816a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1817a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @see #onDependentViewChanged(CoordinatorLayout, android.view.View, android.view.View) 1818a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1819a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean layoutDependsOn(CoordinatorLayout parent, V child, View dependency) { 1820a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return false; 1821a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1822a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1823a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1824a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * Respond to a change in a child's dependent view 1825a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * 1826a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * <p>This method is called whenever a dependent view changes in size or position outside 1827a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * of the standard layout flow. A Behavior may use this method to appropriately update 1828a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * the child view in response.</p> 1829a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1830a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * <p>A view's dependency is determined by 1831a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * {@link #layoutDependsOn(CoordinatorLayout, android.view.View, android.view.View)} or 1832a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * if {@code child} has set another view as it's anchor.</p> 1833a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1834a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>Note that if a Behavior changes the layout of a child via this method, it should 1835a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * also be able to reconstruct the correct position in 1836a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link #onLayoutChild(CoordinatorLayout, android.view.View, int) onLayoutChild}. 1837a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <code>onDependentViewChanged</code> will not be called during normal layout since 1838a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * the layout of each child view will always happen in dependency order.</p> 1839a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1840a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>If the Behavior changes the child view's size or position, it should return true. 1841a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * The default implementation returns false.</p> 1842a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1843a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent view of the given child 1844a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child view to manipulate 1845a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param dependency the dependent view that changed 1846a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true if the Behavior changed the child view's size or position, false otherwise 1847a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1848a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean onDependentViewChanged(CoordinatorLayout parent, V child, View dependency) { 1849a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return false; 1850a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1851a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1852a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 18530b00489086b22c9688c8c04990dadf54489d45e3Chris Banes * Respond to a child's dependent view being removed. 18540b00489086b22c9688c8c04990dadf54489d45e3Chris Banes * 18550b00489086b22c9688c8c04990dadf54489d45e3Chris Banes * <p>This method is called after a dependent view has been removed from the parent. 18560b00489086b22c9688c8c04990dadf54489d45e3Chris Banes * A Behavior may use this method to appropriately update the child view in response.</p> 18570b00489086b22c9688c8c04990dadf54489d45e3Chris Banes * 18580b00489086b22c9688c8c04990dadf54489d45e3Chris Banes * <p>A view's dependency is determined by 18590b00489086b22c9688c8c04990dadf54489d45e3Chris Banes * {@link #layoutDependsOn(CoordinatorLayout, android.view.View, android.view.View)} or 18600b00489086b22c9688c8c04990dadf54489d45e3Chris Banes * if {@code child} has set another view as it's anchor.</p> 18610b00489086b22c9688c8c04990dadf54489d45e3Chris Banes * 18620b00489086b22c9688c8c04990dadf54489d45e3Chris Banes * @param parent the parent view of the given child 18630b00489086b22c9688c8c04990dadf54489d45e3Chris Banes * @param child the child view to manipulate 18640b00489086b22c9688c8c04990dadf54489d45e3Chris Banes * @param dependency the dependent view that has been removed 18650b00489086b22c9688c8c04990dadf54489d45e3Chris Banes */ 18660b00489086b22c9688c8c04990dadf54489d45e3Chris Banes public void onDependentViewRemoved(CoordinatorLayout parent, V child, View dependency) { 18670b00489086b22c9688c8c04990dadf54489d45e3Chris Banes } 18680b00489086b22c9688c8c04990dadf54489d45e3Chris Banes 18690b00489086b22c9688c8c04990dadf54489d45e3Chris Banes /** 1870a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Determine whether the given child view should be considered dirty. 1871a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1872a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>If a property determined by the Behavior such as other dependent views would change, 1873a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * the Behavior should report a child view as dirty. This will prompt the CoordinatorLayout 1874a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * to re-query Behavior-determined properties as appropriate.</p> 1875a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1876a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent view of the given child 1877a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child view to check 1878a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true if child is dirty 1879a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1880a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean isDirty(CoordinatorLayout parent, V child) { 1881a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return false; 1882a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1883a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1884a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1885a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Called when the parent CoordinatorLayout is about to measure the given child view. 1886a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1887a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>This method can be used to perform custom or modified measurement of a child view 1888a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * in place of the default child measurement behavior. The Behavior's implementation 1889a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * can delegate to the standard CoordinatorLayout measurement behavior by calling 1890a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link CoordinatorLayout#onMeasureChild(android.view.View, int, int, int, int) 1891a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * parent.onMeasureChild}.</p> 1892a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1893a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent CoordinatorLayout 1894a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child to measure 1895a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parentWidthMeasureSpec the width requirements for this view 1896a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param widthUsed extra space that has been used up by the parent 1897a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * horizontally (possibly by other children of the parent) 1898a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parentHeightMeasureSpec the height requirements for this view 1899a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param heightUsed extra space that has been used up by the parent 1900a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * vertically (possibly by other children of the parent) 1901a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true if the Behavior measured the child view, false if the CoordinatorLayout 1902a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * should perform its default measurement 1903a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1904a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean onMeasureChild(CoordinatorLayout parent, V child, 1905a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int parentWidthMeasureSpec, int widthUsed, 1906a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int parentHeightMeasureSpec, int heightUsed) { 1907a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return false; 1908a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1909a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1910a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1911a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Called when the parent CoordinatorLayout is about the lay out the given child view. 1912a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1913a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>This method can be used to perform custom or modified layout of a child view 1914a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * in place of the default child layout behavior. The Behavior's implementation can 1915a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * delegate to the standard CoordinatorLayout measurement behavior by calling 1916a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link CoordinatorLayout#onLayoutChild(android.view.View, int) 1917c6d62e6d5ca277d4649c686e76edd63176c7c4e3Chris Banes * parent.onLayoutChild}.</p> 1918a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1919a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>If a Behavior implements 1920a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link #onDependentViewChanged(CoordinatorLayout, android.view.View, android.view.View)} 1921a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * to change the position of a view in response to a dependent view changing, it 1922a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * should also implement <code>onLayoutChild</code> in such a way that respects those 1923a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * dependent views. <code>onLayoutChild</code> will always be called for a dependent view 1924a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <em>after</em> its dependency has been laid out.</p> 1925a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1926a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent CoordinatorLayout 1927a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child view to lay out 1928a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param layoutDirection the resolved layout direction for the CoordinatorLayout, such as 1929a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link ViewCompat#LAYOUT_DIRECTION_LTR} or 1930a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link ViewCompat#LAYOUT_DIRECTION_RTL}. 1931a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true if the Behavior performed layout of the child view, false to request 1932a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * default layout behavior 1933a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1934a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean onLayoutChild(CoordinatorLayout parent, V child, int layoutDirection) { 1935a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return false; 1936a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1937a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1938a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Utility methods for accessing child-specific, behavior-modifiable properties. 1939a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1940a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1941a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Associate a Behavior-specific tag object with the given child view. 1942a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * This object will be stored with the child view's LayoutParams. 1943a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1944a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child view to set tag with 1945a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param tag tag object to set 1946a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1947a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public static void setTag(View child, Object tag) { 1948a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 1949a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell lp.mBehaviorTag = tag; 1950a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1951a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1952a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1953a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Get the behavior-specific tag object with the given child view. 1954a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * This object is stored with the child view's LayoutParams. 1955a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1956a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child view to get tag with 1957a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return the previously stored tag object 1958a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1959a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public static Object getTag(View child) { 1960a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 1961a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return lp.mBehaviorTag; 1962a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 19635cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 19645cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 19655cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell /** 19665cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * Called when a descendant of the CoordinatorLayout attempts to initiate a nested scroll. 19675cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 19685cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p>Any Behavior associated with any direct child of the CoordinatorLayout may respond 19695cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * to this event and return true to indicate that the CoordinatorLayout should act as 19705cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * a nested scrolling parent for this scroll. Only Behaviors that return true from 19715cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * this method will receive subsequent nested scroll events.</p> 19725cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 19735cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is 19745cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * associated with 19755cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param child the child view of the CoordinatorLayout this Behavior is associated with 19765cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param directTargetChild the child view of the CoordinatorLayout that either is or 19775cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * contains the target of the nested scroll operation 19785cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param target the descendant view of the CoordinatorLayout initiating the nested scroll 19795cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param nestedScrollAxes the axes that this nested scroll applies to. See 19805cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * {@link ViewCompat#SCROLL_AXIS_HORIZONTAL}, 19815cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * {@link ViewCompat#SCROLL_AXIS_VERTICAL} 19825cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @return true if the Behavior wishes to accept this nested scroll 19835cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 19845cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @see NestedScrollingParent#onStartNestedScroll(View, View, int) 19855cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell */ 19865cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, 19875cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell V child, View directTargetChild, View target, int nestedScrollAxes) { 19885cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell return false; 19895cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 19905cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 19915cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell /** 19925cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * Called when a nested scroll has been accepted by the CoordinatorLayout. 19935cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 19945cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p>Any Behavior associated with any direct child of the CoordinatorLayout may elect 19955cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * to accept the nested scroll as part of {@link #onStartNestedScroll}. Each Behavior 19965cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * that returned true will receive subsequent nested scroll events for that nested scroll. 19975cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * </p> 19985cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 19995cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is 20005cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * associated with 20015cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param child the child view of the CoordinatorLayout this Behavior is associated with 20025cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param directTargetChild the child view of the CoordinatorLayout that either is or 20035cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * contains the target of the nested scroll operation 20045cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param target the descendant view of the CoordinatorLayout initiating the nested scroll 20055cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param nestedScrollAxes the axes that this nested scroll applies to. See 20065cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * {@link ViewCompat#SCROLL_AXIS_HORIZONTAL}, 20075cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * {@link ViewCompat#SCROLL_AXIS_VERTICAL} 20085cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 20095cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @see NestedScrollingParent#onNestedScrollAccepted(View, View, int) 20105cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell */ 20115cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell public void onNestedScrollAccepted(CoordinatorLayout coordinatorLayout, V child, 20125cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell View directTargetChild, View target, int nestedScrollAxes) { 20135cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell // Do nothing 20145cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 20155cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 20165cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell /** 20175cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * Called when a nested scroll has ended. 20185cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 20195cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p>Any Behavior associated with any direct child of the CoordinatorLayout may elect 20205cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * to accept the nested scroll as part of {@link #onStartNestedScroll}. Each Behavior 20215cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * that returned true will receive subsequent nested scroll events for that nested scroll. 20225cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * </p> 20235cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 20245cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p><code>onStopNestedScroll</code> marks the end of a single nested scroll event 20255cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * sequence. This is a good place to clean up any state related to the nested scroll. 20265cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * </p> 20275cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 20285cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is 20295cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * associated with 20305cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param child the child view of the CoordinatorLayout this Behavior is associated with 20315cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param target the descendant view of the CoordinatorLayout that initiated 20325cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * the nested scroll 20335cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 20345cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @see NestedScrollingParent#onStopNestedScroll(View) 20355cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell */ 20365cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, V child, View target) { 20375cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell // Do nothing 20385cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 20395cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 20405cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell /** 20415cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * Called when a nested scroll in progress has updated and the target has scrolled or 20425cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * attempted to scroll. 20435cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 20445cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p>Any Behavior associated with the direct child of the CoordinatorLayout may elect 20455cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * to accept the nested scroll as part of {@link #onStartNestedScroll}. Each Behavior 20465cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * that returned true will receive subsequent nested scroll events for that nested scroll. 20475cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * </p> 20485cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 20495cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p><code>onNestedScroll</code> is called each time the nested scroll is updated by the 20505cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * nested scrolling child, with both consumed and unconsumed components of the scroll 20515cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * supplied in pixels. <em>Each Behavior responding to the nested scroll will receive the 20525cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * same values.</em> 20535cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * </p> 20545cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 20555cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is 20565cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * associated with 20575cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param child the child view of the CoordinatorLayout this Behavior is associated with 20585cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param target the descendant view of the CoordinatorLayout performing the nested scroll 20595cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param dxConsumed horizontal pixels consumed by the target's own scrolling operation 20605cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param dyConsumed vertical pixels consumed by the target's own scrolling operation 20615cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param dxUnconsumed horizontal pixels not consumed by the target's own scrolling 20625cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * operation, but requested by the user 20635cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param dyUnconsumed vertical pixels not consumed by the target's own scrolling operation, 20645cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * but requested by the user 20655cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 20665cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @see NestedScrollingParent#onNestedScroll(View, int, int, int, int) 20675cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell */ 20685cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell public void onNestedScroll(CoordinatorLayout coordinatorLayout, V child, View target, 20695cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) { 20705cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell // Do nothing 20715cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 20725cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 20735cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell /** 20745cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * Called when a nested scroll in progress is about to update, before the target has 20755cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * consumed any of the scrolled distance. 20765cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 20775cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p>Any Behavior associated with the direct child of the CoordinatorLayout may elect 20785cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * to accept the nested scroll as part of {@link #onStartNestedScroll}. Each Behavior 20795cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * that returned true will receive subsequent nested scroll events for that nested scroll. 20805cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * </p> 20815cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 20825cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p><code>onNestedPreScroll</code> is called each time the nested scroll is updated 20835cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * by the nested scrolling child, before the nested scrolling child has consumed the scroll 20845cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * distance itself. <em>Each Behavior responding to the nested scroll will receive the 20855cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * same values.</em> The CoordinatorLayout will report as consumed the maximum number 20865cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * of pixels in either direction that any Behavior responding to the nested scroll reported 20875cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * as consumed.</p> 20885cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 20895cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is 20905cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * associated with 20915cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param child the child view of the CoordinatorLayout this Behavior is associated with 20925cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param target the descendant view of the CoordinatorLayout performing the nested scroll 20935cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param dx the raw horizontal number of pixels that the user attempted to scroll 20945cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param dy the raw vertical number of pixels that the user attempted to scroll 20955cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param consumed out parameter. consumed[0] should be set to the distance of dx that 20965cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * was consumed, consumed[1] should be set to the distance of dy that 20975cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * was consumed 20985cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 20995cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @see NestedScrollingParent#onNestedPreScroll(View, int, int, int[]) 21005cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell */ 21015cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, V child, View target, 21025cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell int dx, int dy, int[] consumed) { 21035cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell // Do nothing 21045cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 21055cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 21065cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell /** 21075cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * Called when a nested scrolling child is starting a fling or an action that would 21085cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * be a fling. 21095cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 21105cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p>Any Behavior associated with the direct child of the CoordinatorLayout may elect 21115cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * to accept the nested scroll as part of {@link #onStartNestedScroll}. Each Behavior 21125cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * that returned true will receive subsequent nested scroll events for that nested scroll. 21135cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * </p> 21145cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 21155cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p><code>onNestedFling</code> is called when the current nested scrolling child view 21165cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * detects the proper conditions for a fling. It reports if the child itself consumed 21175cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * the fling. If it did not, the child is expected to show some sort of overscroll 21185cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * indication. This method should return true if it consumes the fling, so that a child 21195cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * that did not itself take an action in response can choose not to show an overfling 21205cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * indication.</p> 21215cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 21225cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is 21235cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * associated with 21245cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param child the child view of the CoordinatorLayout this Behavior is associated with 21255cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param target the descendant view of the CoordinatorLayout performing the nested scroll 21265cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param velocityX horizontal velocity of the attempted fling 21275cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param velocityY vertical velocity of the attempted fling 21285cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param consumed true if the nested child view consumed the fling 21295cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @return true if the Behavior consumed the fling 21305cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 21315cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @see NestedScrollingParent#onNestedFling(View, float, float, boolean) 21325cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell */ 21335cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell public boolean onNestedFling(CoordinatorLayout coordinatorLayout, V child, View target, 21345cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell float velocityX, float velocityY, boolean consumed) { 21355cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell return false; 21365cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 21375cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 21385cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell /** 21395cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * Called when a nested scrolling child is about to start a fling. 21405cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 21415cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p>Any Behavior associated with the direct child of the CoordinatorLayout may elect 21425cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * to accept the nested scroll as part of {@link #onStartNestedScroll}. Each Behavior 21435cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * that returned true will receive subsequent nested scroll events for that nested scroll. 21445cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * </p> 21455cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 21465cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p><code>onNestedPreFling</code> is called when the current nested scrolling child view 21475cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * detects the proper conditions for a fling, but it has not acted on it yet. A 21485cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * Behavior can return true to indicate that it consumed the fling. If at least one 21495cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * Behavior returns true, the fling should not be acted upon by the child.</p> 21505cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 21515cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is 21525cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * associated with 21535cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param child the child view of the CoordinatorLayout this Behavior is associated with 21545cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param target the descendant view of the CoordinatorLayout performing the nested scroll 21555cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param velocityX horizontal velocity of the attempted fling 21565cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param velocityY vertical velocity of the attempted fling 21575cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @return true if the Behavior consumed the fling 21585cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 21595cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @see NestedScrollingParent#onNestedPreFling(View, float, float) 21605cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell */ 21615cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell public boolean onNestedPreFling(CoordinatorLayout coordinatorLayout, V child, View target, 21625cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell float velocityX, float velocityY) { 21635cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell return false; 21645cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 216575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 216675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes /** 216775284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * Called when the window insets have changed. 216875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * 216975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * <p>Any Behavior associated with the direct child of the CoordinatorLayout may elect 217075284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * to handle the window inset change on behalf of it's associated view. 217175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * </p> 217275284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * 217375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is 217475284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * associated with 217575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * @param child the child view of the CoordinatorLayout this Behavior is associated with 217675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * @param insets the new window insets. 217775284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * 217875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * @return The insets supplied, minus any insets that were consumed 217975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes */ 218075284fffafacd32f4d178020050589f9e70e5ed9Chris Banes public WindowInsetsCompat onApplyWindowInsets(CoordinatorLayout coordinatorLayout, 218175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes V child, WindowInsetsCompat insets) { 218275284fffafacd32f4d178020050589f9e70e5ed9Chris Banes return insets; 218375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 2184e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2185e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes /** 2186e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * Hook allowing a behavior to re-apply a representation of its internal state that had 2187e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * previously been generated by {@link #onSaveInstanceState}. This function will never 2188e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * be called with a null state. 2189e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * 2190e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * @param parent the parent CoordinatorLayout 2191e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * @param child child view to restore from 2192e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * @param state The frozen state that had previously been returned by 2193e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * {@link #onSaveInstanceState}. 2194e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * 2195e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * @see #onSaveInstanceState() 2196e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes */ 2197e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes public void onRestoreInstanceState(CoordinatorLayout parent, V child, Parcelable state) { 2198e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes // no-op 2199e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2200e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2201e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes /** 2202e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * Hook allowing a behavior to generate a representation of its internal state 2203e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * that can later be used to create a new instance with that same state. 2204e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * This state should only contain information that is not persistent or can 2205e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * not be reconstructed later. 2206e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * 2207e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * <p>Behavior state is only saved when both the parent {@link CoordinatorLayout} and 2208e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * a view using this behavior have valid IDs set.</p> 2209e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * 2210e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * @param parent the parent CoordinatorLayout 2211e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * @param child child view to restore from 2212e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * 2213e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * @return Returns a Parcelable object containing the behavior's current dynamic 2214e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * state. 2215e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * 2216e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * @see #onRestoreInstanceState(android.os.Parcelable) 2217e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * @see View#onSaveInstanceState() 2218e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes */ 2219e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes public Parcelable onSaveInstanceState(CoordinatorLayout parent, V child) { 2220e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes return BaseSavedState.EMPTY_STATE; 2221e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2222a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2223a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2224a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2225a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Parameters describing the desired layout for a child of a {@link CoordinatorLayout}. 2226a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2227a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public static class LayoutParams extends ViewGroup.MarginLayoutParams { 2228a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2229a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * A {@link Behavior} that the child view should obey. 2230a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2231a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Behavior mBehavior; 2232a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2233a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean mBehaviorResolved = false; 2234a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2235a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2236a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * A {@link Gravity} value describing how this child view should lay out. 2237a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * If an {@link #setAnchorId(int) anchor} is also specified, the gravity describes 2238a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * how this child view should be positioned relative to its anchored position. 2239a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2240a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public int gravity = Gravity.NO_GRAVITY; 2241a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2242a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2243a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * A {@link Gravity} value describing which edge of a child view's 2244a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link #getAnchorId() anchor} view the child should position itself relative to. 2245a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2246a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public int anchorGravity = Gravity.NO_GRAVITY; 2247a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2248a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2249a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * The index of the horizontal keyline specified to the parent CoordinatorLayout that this 2250a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * child should align relative to. If an {@link #setAnchorId(int) anchor} is present the 2251a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * keyline will be ignored. 2252a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2253a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public int keyline = -1; 2254a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2255a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2256a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * A {@link View#getId() view id} of a descendant view of the CoordinatorLayout that 2257a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * this child should position relative to. 2258a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2259a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int mAnchorId = View.NO_ID; 2260a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2261a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell View mAnchorView; 2262a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell View mAnchorDirectChild; 2263a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 22645cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell private boolean mDidBlockInteraction; 22655cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell private boolean mDidAcceptNestedScroll; 2266a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes private boolean mDidChangeAfterNestedScroll; 2267a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2268a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Rect mLastChildRect = new Rect(); 2269a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2270a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Object mBehaviorTag; 2271a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2272a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public LayoutParams(int width, int height) { 2273a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell super(width, height); 2274a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2275a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2276a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell LayoutParams(Context context, AttributeSet attrs) { 2277a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell super(context, attrs); 2278a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2279a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final TypedArray a = context.obtainStyledAttributes(attrs, 2280c6cbbb50a06ec08e6888bd1c3dfd7fdf588d9db5Chris Banes R.styleable.CoordinatorLayout_Layout); 2281a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2282a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell this.gravity = a.getInteger( 2283c6cbbb50a06ec08e6888bd1c3dfd7fdf588d9db5Chris Banes R.styleable.CoordinatorLayout_Layout_android_layout_gravity, 2284a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Gravity.NO_GRAVITY); 2285c6cbbb50a06ec08e6888bd1c3dfd7fdf588d9db5Chris Banes mAnchorId = a.getResourceId(R.styleable.CoordinatorLayout_Layout_layout_anchor, 2286a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell View.NO_ID); 2287a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell this.anchorGravity = a.getInteger( 2288c6cbbb50a06ec08e6888bd1c3dfd7fdf588d9db5Chris Banes R.styleable.CoordinatorLayout_Layout_layout_anchorGravity, 2289a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Gravity.NO_GRAVITY); 2290a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2291c6cbbb50a06ec08e6888bd1c3dfd7fdf588d9db5Chris Banes this.keyline = a.getInteger(R.styleable.CoordinatorLayout_Layout_layout_keyline, 2292a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell -1); 2293a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2294a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mBehaviorResolved = a.hasValue( 2295c6cbbb50a06ec08e6888bd1c3dfd7fdf588d9db5Chris Banes R.styleable.CoordinatorLayout_Layout_layout_behavior); 2296a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mBehaviorResolved) { 2297a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mBehavior = parseBehavior(context, attrs, a.getString( 2298c6cbbb50a06ec08e6888bd1c3dfd7fdf588d9db5Chris Banes R.styleable.CoordinatorLayout_Layout_layout_behavior)); 2299a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2300a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2301a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell a.recycle(); 2302a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2303a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2304a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public LayoutParams(LayoutParams p) { 2305a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell super(p); 2306a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2307a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2308a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public LayoutParams(MarginLayoutParams p) { 2309a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell super(p); 2310a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2311a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2312a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public LayoutParams(ViewGroup.LayoutParams p) { 2313a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell super(p); 2314a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2315a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2316a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2317a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Get the id of this view's anchor. 2318a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2319a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return A {@link View#getId() view id} or {@link View#NO_ID} if there is no anchor 2320a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2321a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public int getAnchorId() { 2322a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return mAnchorId; 2323a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2324a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2325a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2326c344398708c615b0caba76d287e9ec503afa6819Mady Mellor * Set the id of this view's anchor. 2327a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2328a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>The view with this id must be a descendant of the CoordinatorLayout containing 2329a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * the child view this LayoutParams belongs to. It may not be the child view with 2330a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * this LayoutParams or a descendant of it.</p> 2331a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2332a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param id The {@link View#getId() view id} of the anchor or 2333a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link View#NO_ID} if there is no anchor 2334a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2335a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public void setAnchorId(int id) { 2336a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell invalidateAnchor(); 2337a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mAnchorId = id; 2338a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2339a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2340a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2341a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Get the behavior governing the layout and interaction of the child view within 2342a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * a parent CoordinatorLayout. 2343a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2344a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return The current behavior or null if no behavior is specified 2345a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2346a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public Behavior getBehavior() { 2347a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return mBehavior; 2348a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2349a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2350a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2351a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Set the behavior governing the layout and interaction of the child view within 2352a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * a parent CoordinatorLayout. 2353a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2354a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>Setting a new behavior will remove any currently associated 2355a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link Behavior#setTag(android.view.View, Object) Behavior tag}.</p> 2356a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2357a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param behavior The behavior to set or null for no special behavior 2358a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2359a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public void setBehavior(Behavior behavior) { 2360a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mBehavior != behavior) { 2361a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mBehavior = behavior; 2362a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mBehaviorTag = null; 2363a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mBehaviorResolved = true; 2364a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2365a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2366a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2367a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2368a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Set the last known position rect for this child view 2369a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param r the rect to set 2370a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2371a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void setLastChildRect(Rect r) { 2372a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mLastChildRect.set(r); 2373a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2374a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2375a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2376a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Get the last known position rect for this child view. 2377a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Note: do not mutate the result of this call. 2378a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2379a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Rect getLastChildRect() { 2380a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return mLastChildRect; 2381a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2382a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2383a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2384a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Returns true if the anchor id changed to another valid view id since the anchor view 2385a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * was resolved. 2386a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2387a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean checkAnchorChanged() { 2388a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return mAnchorView == null && mAnchorId != View.NO_ID; 2389a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2390a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2391a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2392a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Returns true if the associated Behavior previously blocked interaction with other views 2393a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * below the associated child since the touch behavior tracking was last 2394a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link #resetTouchBehaviorTracking() reset}. 2395a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2396a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @see #isBlockingInteractionBelow(CoordinatorLayout, android.view.View) 2397a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2398a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean didBlockInteraction() { 2399a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mBehavior == null) { 2400a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mDidBlockInteraction = false; 2401a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2402a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return mDidBlockInteraction; 2403a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2404a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2405a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2406a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Check if the associated Behavior wants to block interaction below the given child 2407a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * view. The given child view should be the child this LayoutParams is associated with. 2408a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2409a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>Once interaction is blocked, it will remain blocked until touch interaction tracking 2410a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * is {@link #resetTouchBehaviorTracking() reset}.</p> 2411a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2412a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent CoordinatorLayout 2413a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child view this LayoutParams is associated with 2414a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true to block interaction below the given child 2415a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2416a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean isBlockingInteractionBelow(CoordinatorLayout parent, View child) { 2417a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mDidBlockInteraction) { 2418a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return true; 2419a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2420a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2421a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return mDidBlockInteraction |= mBehavior != null 2422a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell ? mBehavior.blocksInteractionBelow(parent, child) 2423a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell : false; 2424a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2425a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2426a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2427a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Reset tracking of Behavior-specific touch interactions. This includes 2428a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * interaction blocking. 2429a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2430a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @see #isBlockingInteractionBelow(CoordinatorLayout, android.view.View) 2431a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @see #didBlockInteraction() 2432a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2433a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void resetTouchBehaviorTracking() { 2434a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mDidBlockInteraction = false; 2435a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2436a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 24375cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell void resetNestedScroll() { 24385cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell mDidAcceptNestedScroll = false; 24395cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 24405cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 24415cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell void acceptNestedScroll(boolean accept) { 24425cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell mDidAcceptNestedScroll = accept; 24435cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 24445cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 24455cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell boolean isNestedScrollAccepted() { 24465cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell return mDidAcceptNestedScroll; 24475cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 24485cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 2449a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes boolean getChangedAfterNestedScroll() { 2450a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes return mDidChangeAfterNestedScroll; 2451a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 2452a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 2453a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes void setChangedAfterNestedScroll(boolean changed) { 2454a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes mDidChangeAfterNestedScroll = changed; 2455a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 2456a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 2457a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes void resetChangedAfterNestedScroll() { 2458a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes mDidChangeAfterNestedScroll = false; 2459a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 2460a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 2461a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2462a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Check if an associated child view depends on another child view of the CoordinatorLayout. 2463a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2464a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent CoordinatorLayout 2465a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child to check 2466a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param dependency the proposed dependency to check 2467a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true if child depends on dependency 2468a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2469a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean dependsOn(CoordinatorLayout parent, View child, View dependency) { 2470a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return dependency == mAnchorDirectChild 2471a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell || (mBehavior != null && mBehavior.layoutDependsOn(parent, child, dependency)); 2472a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2473a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2474a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2475a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Invalidate the cached anchor view and direct child ancestor of that anchor. 2476a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * The anchor will need to be 2477a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link #findAnchorView(CoordinatorLayout, android.view.View) found} before 2478a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * being used again. 2479a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2480a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void invalidateAnchor() { 2481a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mAnchorView = mAnchorDirectChild = null; 2482a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2483a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2484a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2485a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Locate the appropriate anchor view by the current {@link #setAnchorId(int) anchor id} 2486a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * or return the cached anchor view if already known. 2487a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2488a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent CoordinatorLayout 2489a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param forChild the child this LayoutParams is associated with 2490a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return the located descendant anchor view, or null if the anchor id is 2491a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link View#NO_ID}. 2492a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2493a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell View findAnchorView(CoordinatorLayout parent, View forChild) { 2494a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mAnchorId == View.NO_ID) { 2495a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mAnchorView = mAnchorDirectChild = null; 2496a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return null; 2497a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2498a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2499a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mAnchorView == null || !verifyAnchorView(forChild, parent)) { 2500a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell resolveAnchorView(forChild, parent); 2501a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2502a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return mAnchorView; 2503a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2504a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2505a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2506a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Check if the child associated with this LayoutParams is currently considered 2507a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * "dirty" and needs to be updated. A Behavior should consider a child dirty 2508a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * whenever a property returned by another Behavior method would have changed, 2509a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * such as dependencies. 2510a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2511a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent CoordinatorLayout 2512a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child view associated with this LayoutParams 2513a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true if this child view should be considered dirty 2514a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2515a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean isDirty(CoordinatorLayout parent, View child) { 2516a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return mBehavior != null && mBehavior.isDirty(parent, child); 2517a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2518a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2519a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2520a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Determine the anchor view for the child view this LayoutParams is assigned to. 2521a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Assumes mAnchorId is valid. 2522a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2523375995f4dc8aecb335bb262190d2cd39fdb136d6Chris Banes private void resolveAnchorView(final View forChild, final CoordinatorLayout parent) { 2524a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mAnchorView = parent.findViewById(mAnchorId); 2525a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mAnchorView != null) { 2526375995f4dc8aecb335bb262190d2cd39fdb136d6Chris Banes if (mAnchorView == parent) { 2527375995f4dc8aecb335bb262190d2cd39fdb136d6Chris Banes if (parent.isInEditMode()) { 2528375995f4dc8aecb335bb262190d2cd39fdb136d6Chris Banes mAnchorView = mAnchorDirectChild = null; 2529375995f4dc8aecb335bb262190d2cd39fdb136d6Chris Banes return; 2530375995f4dc8aecb335bb262190d2cd39fdb136d6Chris Banes } 2531375995f4dc8aecb335bb262190d2cd39fdb136d6Chris Banes throw new IllegalStateException( 2532375995f4dc8aecb335bb262190d2cd39fdb136d6Chris Banes "View can not be anchored to the the parent CoordinatorLayout"); 2533375995f4dc8aecb335bb262190d2cd39fdb136d6Chris Banes } 2534375995f4dc8aecb335bb262190d2cd39fdb136d6Chris Banes 2535a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell View directChild = mAnchorView; 2536a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (ViewParent p = mAnchorView.getParent(); 2537a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell p != parent && p != null; 2538a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell p = p.getParent()) { 2539a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (p == forChild) { 2540a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (parent.isInEditMode()) { 2541a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mAnchorView = mAnchorDirectChild = null; 2542a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return; 2543a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2544a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell throw new IllegalStateException( 2545a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell "Anchor must not be a descendant of the anchored view"); 2546a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2547a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (p instanceof View) { 2548a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell directChild = (View) p; 2549a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2550a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2551a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mAnchorDirectChild = directChild; 2552a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else { 2553a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (parent.isInEditMode()) { 2554a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mAnchorView = mAnchorDirectChild = null; 2555a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return; 2556a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2557a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell throw new IllegalStateException("Could not find CoordinatorLayout descendant view" 2558a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell + " with id " + parent.getResources().getResourceName(mAnchorId) 2559a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell + " to anchor view " + forChild); 2560a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2561a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2562a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2563a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2564a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Verify that the previously resolved anchor view is still valid - that it is still 2565a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * a descendant of the expected parent view, it is not the child this LayoutParams 2566a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * is assigned to or a descendant of it, and it has the expected id. 2567a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2568a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private boolean verifyAnchorView(View forChild, CoordinatorLayout parent) { 2569a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mAnchorView.getId() != mAnchorId) { 2570a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return false; 2571a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2572a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2573a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell View directChild = mAnchorView; 2574a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (ViewParent p = mAnchorView.getParent(); 2575a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell p != parent; 2576a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell p = p.getParent()) { 2577a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (p == null || p == forChild) { 2578a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mAnchorView = mAnchorDirectChild = null; 2579a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return false; 2580a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2581a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (p instanceof View) { 2582a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell directChild = (View) p; 2583a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2584a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2585a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mAnchorDirectChild = directChild; 2586a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return true; 2587a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2588a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 258975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 259017ed3263761329f6aa6796941358c41001fff325Chris Banes private class ApplyInsetsListener 259117ed3263761329f6aa6796941358c41001fff325Chris Banes implements android.support.v4.view.OnApplyWindowInsetsListener { 259275284fffafacd32f4d178020050589f9e70e5ed9Chris Banes @Override 259375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes public WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat insets) { 259417ed3263761329f6aa6796941358c41001fff325Chris Banes return setWindowInsets(insets); 259575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 259675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 2597e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 259817ed3263761329f6aa6796941358c41001fff325Chris Banes private class HierarchyChangeListener implements OnHierarchyChangeListener { 25990b00489086b22c9688c8c04990dadf54489d45e3Chris Banes @Override 26000b00489086b22c9688c8c04990dadf54489d45e3Chris Banes public void onChildViewAdded(View parent, View child) { 26010b00489086b22c9688c8c04990dadf54489d45e3Chris Banes if (mOnHierarchyChangeListener != null) { 26020b00489086b22c9688c8c04990dadf54489d45e3Chris Banes mOnHierarchyChangeListener.onChildViewAdded(parent, child); 26030b00489086b22c9688c8c04990dadf54489d45e3Chris Banes } 26040b00489086b22c9688c8c04990dadf54489d45e3Chris Banes } 26050b00489086b22c9688c8c04990dadf54489d45e3Chris Banes 26060b00489086b22c9688c8c04990dadf54489d45e3Chris Banes @Override 26070b00489086b22c9688c8c04990dadf54489d45e3Chris Banes public void onChildViewRemoved(View parent, View child) { 26080b00489086b22c9688c8c04990dadf54489d45e3Chris Banes dispatchDependentViewRemoved(child); 26090b00489086b22c9688c8c04990dadf54489d45e3Chris Banes 26100b00489086b22c9688c8c04990dadf54489d45e3Chris Banes if (mOnHierarchyChangeListener != null) { 26110b00489086b22c9688c8c04990dadf54489d45e3Chris Banes mOnHierarchyChangeListener.onChildViewRemoved(parent, child); 26120b00489086b22c9688c8c04990dadf54489d45e3Chris Banes } 26130b00489086b22c9688c8c04990dadf54489d45e3Chris Banes } 26140b00489086b22c9688c8c04990dadf54489d45e3Chris Banes } 26150b00489086b22c9688c8c04990dadf54489d45e3Chris Banes 2616e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes @Override 2617e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes protected void onRestoreInstanceState(Parcelable state) { 2618b8af67a0b7896d08b81a803b3880dafaddc7e0bcAlan Viverette if (!(state instanceof SavedState)) { 2619b8af67a0b7896d08b81a803b3880dafaddc7e0bcAlan Viverette super.onRestoreInstanceState(state); 2620b8af67a0b7896d08b81a803b3880dafaddc7e0bcAlan Viverette return; 2621b8af67a0b7896d08b81a803b3880dafaddc7e0bcAlan Viverette } 2622b8af67a0b7896d08b81a803b3880dafaddc7e0bcAlan Viverette 2623e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final SavedState ss = (SavedState) state; 2624e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes super.onRestoreInstanceState(ss.getSuperState()); 2625e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2626e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final SparseArray<Parcelable> behaviorStates = ss.behaviorStates; 2627e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2628e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes for (int i = 0, count = getChildCount(); i < count; i++) { 2629e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final View child = getChildAt(i); 2630e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final int childId = child.getId(); 2631e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final LayoutParams lp = getResolvedLayoutParams(child); 2632e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final Behavior b = lp.getBehavior(); 2633e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2634e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes if (childId != NO_ID && b != null) { 2635e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes Parcelable savedState = behaviorStates.get(childId); 2636e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes if (savedState != null) { 2637e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes b.onRestoreInstanceState(this, child, savedState); 2638e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2639e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2640e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2641e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2642e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2643e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes @Override 2644e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes protected Parcelable onSaveInstanceState() { 2645e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final SavedState ss = new SavedState(super.onSaveInstanceState()); 2646e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2647e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final SparseArray<Parcelable> behaviorStates = new SparseArray<>(); 2648e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes for (int i = 0, count = getChildCount(); i < count; i++) { 2649e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final View child = getChildAt(i); 2650e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final int childId = child.getId(); 2651e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 2652e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final Behavior b = lp.getBehavior(); 2653e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2654e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes if (childId != NO_ID && b != null) { 2655e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes // If the child has an ID and a Behavior, let it save some state... 2656e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes Parcelable state = b.onSaveInstanceState(this, child); 2657e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes if (state != null) { 2658e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes behaviorStates.append(childId, state); 2659e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2660e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2661e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2662e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes ss.behaviorStates = behaviorStates; 2663e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes return ss; 2664e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2665e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 266605f5ba020fa6caa658c75b6d77436aa980ca0fccChris Banes protected static class SavedState extends AbsSavedState { 2667e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes SparseArray<Parcelable> behaviorStates; 2668e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 266962ab25d71ccfa775a8bd2add7b41277bc4e14bbcChris Banes public SavedState(Parcel source, ClassLoader loader) { 267005f5ba020fa6caa658c75b6d77436aa980ca0fccChris Banes super(source, loader); 2671e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2672e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final int size = source.readInt(); 2673e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2674e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final int[] ids = new int[size]; 2675e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes source.readIntArray(ids); 2676e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 267762ab25d71ccfa775a8bd2add7b41277bc4e14bbcChris Banes final Parcelable[] states = source.readParcelableArray(loader); 2678e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2679e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes behaviorStates = new SparseArray<>(size); 2680e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes for (int i = 0; i < size; i++) { 2681e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes behaviorStates.append(ids[i], states[i]); 2682e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2683e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2684e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2685e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes public SavedState(Parcelable superState) { 2686e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes super(superState); 2687e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2688e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2689e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes @Override 2690e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes public void writeToParcel(Parcel dest, int flags) { 2691e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes super.writeToParcel(dest, flags); 2692e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2693e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final int size = behaviorStates != null ? behaviorStates.size() : 0; 2694e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes dest.writeInt(size); 2695e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2696e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final int[] ids = new int[size]; 2697e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final Parcelable[] states = new Parcelable[size]; 2698e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2699e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes for (int i = 0; i < size; i++) { 2700e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes ids[i] = behaviorStates.keyAt(i); 2701e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes states[i] = behaviorStates.valueAt(i); 2702e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2703e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes dest.writeIntArray(ids); 2704e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes dest.writeParcelableArray(states, flags); 2705e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2706e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2707e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 270862ab25d71ccfa775a8bd2add7b41277bc4e14bbcChris Banes public static final Parcelable.Creator<SavedState> CREATOR 270962ab25d71ccfa775a8bd2add7b41277bc4e14bbcChris Banes = ParcelableCompat.newCreator(new ParcelableCompatCreatorCallbacks<SavedState>() { 271062ab25d71ccfa775a8bd2add7b41277bc4e14bbcChris Banes @Override 271162ab25d71ccfa775a8bd2add7b41277bc4e14bbcChris Banes public SavedState createFromParcel(Parcel in, ClassLoader loader) { 271262ab25d71ccfa775a8bd2add7b41277bc4e14bbcChris Banes return new SavedState(in, loader); 271362ab25d71ccfa775a8bd2add7b41277bc4e14bbcChris Banes } 2714e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 271562ab25d71ccfa775a8bd2add7b41277bc4e14bbcChris Banes @Override 271662ab25d71ccfa775a8bd2add7b41277bc4e14bbcChris Banes public SavedState[] newArray(int size) { 271762ab25d71ccfa775a8bd2add7b41277bc4e14bbcChris Banes return new SavedState[size]; 271862ab25d71ccfa775a8bd2add7b41277bc4e14bbcChris Banes } 271962ab25d71ccfa775a8bd2add7b41277bc4e14bbcChris Banes }); 2720e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2721cea5e20817a848367e82e69b00d091c8405c99fcChris Banes 2722cea5e20817a848367e82e69b00d091c8405c99fcChris Banes private static void selectionSort(final List<View> list, final Comparator<View> comparator) { 2723cea5e20817a848367e82e69b00d091c8405c99fcChris Banes if (list == null || list.size() < 2) { 2724cea5e20817a848367e82e69b00d091c8405c99fcChris Banes return; 2725cea5e20817a848367e82e69b00d091c8405c99fcChris Banes } 2726cea5e20817a848367e82e69b00d091c8405c99fcChris Banes 2727cea5e20817a848367e82e69b00d091c8405c99fcChris Banes final View[] array = new View[list.size()]; 2728cea5e20817a848367e82e69b00d091c8405c99fcChris Banes list.toArray(array); 2729cea5e20817a848367e82e69b00d091c8405c99fcChris Banes final int count = array.length; 2730cea5e20817a848367e82e69b00d091c8405c99fcChris Banes 2731cea5e20817a848367e82e69b00d091c8405c99fcChris Banes for (int i = 0; i < count; i++) { 2732cea5e20817a848367e82e69b00d091c8405c99fcChris Banes int min = i; 2733cea5e20817a848367e82e69b00d091c8405c99fcChris Banes 2734cea5e20817a848367e82e69b00d091c8405c99fcChris Banes for (int j = i + 1; j < count; j++) { 2735cea5e20817a848367e82e69b00d091c8405c99fcChris Banes if (comparator.compare(array[j], array[min]) < 0) { 2736cea5e20817a848367e82e69b00d091c8405c99fcChris Banes min = j; 2737cea5e20817a848367e82e69b00d091c8405c99fcChris Banes } 2738cea5e20817a848367e82e69b00d091c8405c99fcChris Banes } 2739cea5e20817a848367e82e69b00d091c8405c99fcChris Banes 2740cea5e20817a848367e82e69b00d091c8405c99fcChris Banes if (i != min) { 2741cea5e20817a848367e82e69b00d091c8405c99fcChris Banes // We have a different min so swap the items 2742cea5e20817a848367e82e69b00d091c8405c99fcChris Banes final View minItem = array[min]; 2743cea5e20817a848367e82e69b00d091c8405c99fcChris Banes array[min] = array[i]; 2744cea5e20817a848367e82e69b00d091c8405c99fcChris Banes array[i] = minItem; 2745cea5e20817a848367e82e69b00d091c8405c99fcChris Banes } 2746cea5e20817a848367e82e69b00d091c8405c99fcChris Banes } 2747cea5e20817a848367e82e69b00d091c8405c99fcChris Banes 2748cea5e20817a848367e82e69b00d091c8405c99fcChris Banes // Finally add the array back into the collection 2749cea5e20817a848367e82e69b00d091c8405c99fcChris Banes list.clear(); 2750cea5e20817a848367e82e69b00d091c8405c99fcChris Banes for (int i = 0; i < count; i++) { 2751cea5e20817a848367e82e69b00d091c8405c99fcChris Banes list.add(array[i]); 2752cea5e20817a848367e82e69b00d091c8405c99fcChris Banes } 2753cea5e20817a848367e82e69b00d091c8405c99fcChris Banes } 2754a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell} 2755