CoordinatorLayout.java revision 878384f1e6de7bd9196958224ced1ecfca3be6a7
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; 26a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.os.Build; 27a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.os.SystemClock; 28a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.support.design.R; 29a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.support.v4.view.GravityCompat; 30a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.support.v4.view.NestedScrollingParent; 31a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.support.v4.view.NestedScrollingParentHelper; 32a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.support.v4.view.ViewCompat; 33a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.text.TextUtils; 34a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.util.AttributeSet; 35a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.util.Log; 36a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.view.Gravity; 37a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.view.MotionEvent; 38a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.view.View; 39a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.view.ViewGroup; 40a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.view.ViewParent; 41a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.view.ViewTreeObserver; 42a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 43a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport java.lang.annotation.Retention; 44a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport java.lang.annotation.RetentionPolicy; 45a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport java.lang.reflect.Constructor; 46a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport java.util.ArrayList; 47a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport java.util.Collections; 48a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport java.util.Comparator; 49a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport java.util.HashMap; 50a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport java.util.List; 51a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport java.util.Map; 52a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 53a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell/** 54a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * CoordinatorLayout is a super-powered {@link android.widget.FrameLayout FrameLayout}. 55a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 56a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>CoordinatorLayout is intended for two primary use cases:</p> 57a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <ol> 58a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <li>As a top-level application decor or chrome layout</li> 59a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <li>As a container for a specific interaction with one or more child views</li> 60a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * </ol> 61a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 62a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>By specifying {@link CoordinatorLayout.Behavior Behaviors} for child views of a 63a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * CoordinatorLayout you can provide many different interactions within a single parent and those 64a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * views can also interact with one another. View classes can specify a default behavior when 65a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * used as a child of a CoordinatorLayout using the 66a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link CoordinatorLayout.DefaultBehavior DefaultBehavior} annotation.</p> 67a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 68a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>Behaviors may be used to implement a variety of interactions and additional layout 69a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * modifications ranging from sliding drawers and panels to swipe-dismissable elements and buttons 70a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * that stick to other elements as they move and animate.</p> 71a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 72a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>Children of a CoordinatorLayout may have an 73a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link CoordinatorLayout.LayoutParams#setAnchorId(int) anchor}. This view id must correspond 74a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * to an arbitrary descendant of the CoordinatorLayout, but it may not be the anchored child itself 75a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * or a descendant of the anchored child. This can be used to place floating views relative to 76a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * other arbitrary content panes.</p> 77a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 78a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellpublic class CoordinatorLayout extends ViewGroup implements NestedScrollingParent { 79a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell static final String TAG = "CoordinatorLayout"; 80a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell static final String WIDGET_PACKAGE_NAME = CoordinatorLayout.class.getPackage().getName(); 81a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 82a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell static { 83a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes if (Build.VERSION.SDK_INT >= 21) { 84a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell TOP_SORTED_CHILDREN_COMPARATOR = new ViewElevationComparator(); 85a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else { 86a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell TOP_SORTED_CHILDREN_COMPARATOR = null; 87a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 88a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 89a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 90a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell static final Class<?>[] CONSTRUCTOR_PARAMS = new Class<?>[] { 91a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Context.class, 92a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell AttributeSet.class 93a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell }; 94a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 95a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell static final ThreadLocal<Map<String, Constructor<Behavior>>> sConstructors = 96a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell new ThreadLocal<>(); 97a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 98a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Comparator<View> mLayoutDependencyComparator = new Comparator<View>() { 99a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 100a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public int compare(View lhs, View rhs) { 101a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (lhs == rhs) { 102a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return 0; 103a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else if (((LayoutParams) lhs.getLayoutParams()).dependsOn( 104a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell CoordinatorLayout.this, lhs, rhs)) { 105a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return 1; 106a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else if (((LayoutParams) rhs.getLayoutParams()).dependsOn( 107a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell CoordinatorLayout.this, rhs, lhs)) { 108a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return -1; 109a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else { 110a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return 0; 111a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 112a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 113a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell }; 114a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 115a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell static final Comparator<View> TOP_SORTED_CHILDREN_COMPARATOR; 116a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 117a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private final List<View> mDependencySortedChildren = new ArrayList<View>(); 118a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes private final List<View> mTempList1 = new ArrayList<>(); 119a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes private final List<View> mTempDependenciesList = new ArrayList<>(); 120a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private final Rect mTempRect1 = new Rect(); 121a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private final Rect mTempRect2 = new Rect(); 122a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private final Rect mTempRect3 = new Rect(); 1235cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell private final int[] mTempIntPair = new int[2]; 124a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private Paint mScrimPaint; 125a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 126a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private boolean mIsAttachedToWindow; 127a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 128a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private int[] mKeylines; 129a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 130a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private View mBehaviorTouchView; 1315cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell private View mNestedScrollingDirectChild; 1325cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell private View mNestedScrollingTarget; 133a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 134a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private OnPreDrawListener mOnPreDrawListener; 135a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private boolean mNeedsPreDrawListener; 136a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 137a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private final NestedScrollingParentHelper mNestedScrollingParentHelper = 138a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell new NestedScrollingParentHelper(this); 139a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 140a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public CoordinatorLayout(Context context) { 141a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell this(context, null); 142a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 143a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 144a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public CoordinatorLayout(Context context, AttributeSet attrs) { 145a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell this(context, attrs, 0); 146a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 147a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 148a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public CoordinatorLayout(Context context, AttributeSet attrs, int defStyleAttr) { 149a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell super(context, attrs, defStyleAttr); 150a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 151a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CoordinatorLayout, 152a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell defStyleAttr, 0); 153a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int keylineArrayRes = a.getResourceId(R.styleable.CoordinatorLayout_keylines, 0); 154a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (keylineArrayRes != 0) { 155a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Resources res = context.getResources(); 156a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mKeylines = res.getIntArray(keylineArrayRes); 157a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final float density = res.getDisplayMetrics().density; 158a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int count = mKeylines.length; 159a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int i = 0; i < count; i++) { 160a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mKeylines[i] *= density; 161a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 162a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 163a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell a.recycle(); 164a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 165a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 166a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 167a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public void onAttachedToWindow() { 168a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell super.onAttachedToWindow(); 1695cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell resetTouchBehaviors(); 170a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mNeedsPreDrawListener) { 171a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mOnPreDrawListener == null) { 172a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mOnPreDrawListener = new OnPreDrawListener(); 173a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 174a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final ViewTreeObserver vto = getViewTreeObserver(); 175a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell vto.addOnPreDrawListener(mOnPreDrawListener); 176a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 177a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mIsAttachedToWindow = true; 178a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 179a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 180a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 181a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public void onDetachedFromWindow() { 182a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell super.onDetachedFromWindow(); 1835cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell resetTouchBehaviors(); 184a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mNeedsPreDrawListener && mOnPreDrawListener != null) { 185a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final ViewTreeObserver vto = getViewTreeObserver(); 186a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell vto.removeOnPreDrawListener(mOnPreDrawListener); 187a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1885cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (mNestedScrollingTarget != null) { 1895cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell onStopNestedScroll(mNestedScrollingTarget); 1905cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 191a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mIsAttachedToWindow = false; 192a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 193a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 194a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 195a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Reset all Behavior-related tracking records either to clean up or in preparation 196a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * for a new event stream. This should be called when attached or detached from a window, 197a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * in response to an UP or CANCEL event, when intercept is request-disallowed 198a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * and similar cases where an event stream in progress will be aborted. 199a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2005cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell private void resetTouchBehaviors() { 201a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mBehaviorTouchView != null) { 202a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Behavior b = ((LayoutParams) mBehaviorTouchView.getLayoutParams()).getBehavior(); 203a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (b != null) { 204a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final long now = SystemClock.uptimeMillis(); 205a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final MotionEvent cancelEvent = MotionEvent.obtain(now, now, 206a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0); 207a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell b.onTouchEvent(this, mBehaviorTouchView, cancelEvent); 208a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell cancelEvent.recycle(); 209a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 210a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mBehaviorTouchView = null; 211a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 212a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 213a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childCount = getChildCount(); 214a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int i = 0; i < childCount; i++) { 215a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final View child = getChildAt(i); 216a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 217a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell lp.resetTouchBehaviorTracking(); 218a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 219a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 220a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 221a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 222a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Populate a list with the current child views, sorted such that the topmost views 223a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * in z-order are at the front of the list. Useful for hit testing and event dispatch. 224a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 225a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private void getTopSortedChildren(List<View> out) { 226a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell out.clear(); 227a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 228a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final boolean useCustomOrder = isChildrenDrawingOrderEnabled(); 229a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childCount = getChildCount(); 230a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int i = childCount - 1; i >= 0; i--) { 231a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childIndex = useCustomOrder ? getChildDrawingOrder(childCount, i) : i; 232a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final View child = getChildAt(childIndex); 233a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell out.add(child); 234a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 235a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 236a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (TOP_SORTED_CHILDREN_COMPARATOR != null) { 237a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Collections.sort(out, TOP_SORTED_CHILDREN_COMPARATOR); 238a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 239a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 240a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 241a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private boolean performIntercept(MotionEvent ev) { 242a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean intercepted = false; 243a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean newBlock = false; 244a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 245a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell MotionEvent cancelEvent = null; 246a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 247a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int action = ev.getActionMasked(); 248a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 249a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes final List<View> topmostChildList = mTempList1; 250a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getTopSortedChildren(topmostChildList); 251a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 252a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Let topmost child views inspect first 253a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childCount = topmostChildList.size(); 254a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int i = 0; i < childCount; i++) { 255a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final View child = topmostChildList.get(i); 256a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 257a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Behavior b = lp.getBehavior(); 258a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 259a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if ((intercepted || newBlock) && action != MotionEvent.ACTION_DOWN) { 260a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Cancel all behaviors beneath the one that intercepted. 261a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // If the event is "down" then we don't have anything to cancel yet. 262a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (b != null) { 263a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (cancelEvent != null) { 264a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final long now = SystemClock.uptimeMillis(); 265a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell cancelEvent = MotionEvent.obtain(now, now, 266a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0); 267a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 268a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell b.onInterceptTouchEvent(this, child, cancelEvent); 269a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 270a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell continue; 271a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 272a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 273a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (!intercepted && b != null 274a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell && (intercepted = b.onInterceptTouchEvent(this, child, ev))) { 275a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mBehaviorTouchView = child; 276a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 277a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 278a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Don't keep going if we're not allowing interaction below this. 279a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Setting newBlock will make sure we cancel the rest of the behaviors. 280a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final boolean wasBlocking = lp.didBlockInteraction(); 281a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final boolean isBlocking = lp.isBlockingInteractionBelow(this, child); 282a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell newBlock = isBlocking && !wasBlocking; 283a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (isBlocking && !newBlock) { 284a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Stop here since we don't have anything more to cancel - we already did 285a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // when the behavior first started blocking things below this point. 286a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 287a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 288a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 289a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 290a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell topmostChildList.clear(); 291a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 292a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return intercepted; 293a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 294a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 295a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 296a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean onInterceptTouchEvent(MotionEvent ev) { 297a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell MotionEvent cancelEvent = null; 298a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 299a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int action = ev.getActionMasked(); 300a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 301a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Make sure we reset in case we had missed a previous important event. 302a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (action == MotionEvent.ACTION_DOWN) { 3035cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell resetTouchBehaviors(); 304a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 305a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 306a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final boolean intercepted = performIntercept(ev); 307a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 308a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (cancelEvent != null) { 309a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell cancelEvent.recycle(); 310a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 311a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 312a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { 3135cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell resetTouchBehaviors(); 314a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 315a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 316a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return intercepted; 317a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 318a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 319a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 320a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean onTouchEvent(MotionEvent ev) { 321a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean handled = false; 322a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean cancelSuper = false; 323a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell MotionEvent cancelEvent = null; 324a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 325a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int action = ev.getActionMasked(); 326a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 327a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mBehaviorTouchView != null || (cancelSuper = performIntercept(ev))) { 328a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Safe since performIntercept guarantees that 329a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // mBehaviorTouchView != null if it returns true 330ecc58a45a7bdd60d9b71e6c413b80a3f8cf85822Chris Banes final LayoutParams lp = (LayoutParams) mBehaviorTouchView.getLayoutParams(); 331ecc58a45a7bdd60d9b71e6c413b80a3f8cf85822Chris Banes final Behavior b = lp.getBehavior(); 332ecc58a45a7bdd60d9b71e6c413b80a3f8cf85822Chris Banes if (b != null) { 333ecc58a45a7bdd60d9b71e6c413b80a3f8cf85822Chris Banes b.onTouchEvent(this, mBehaviorTouchView, ev); 334ecc58a45a7bdd60d9b71e6c413b80a3f8cf85822Chris Banes } 335a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 336a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 337a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Keep the super implementation correct 338a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mBehaviorTouchView == null) { 339a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell handled |= super.onTouchEvent(ev); 340a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else if (cancelSuper) { 341a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (cancelEvent != null) { 342a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final long now = SystemClock.uptimeMillis(); 343a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell cancelEvent = MotionEvent.obtain(now, now, 344a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0); 345a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 346a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell super.onTouchEvent(cancelEvent); 347a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 348a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 349a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (!handled && action == MotionEvent.ACTION_DOWN) { 350a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 351a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 352a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 353a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (cancelEvent != null) { 354a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell cancelEvent.recycle(); 355a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 356a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 357a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { 3585cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell resetTouchBehaviors(); 359a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 360a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 361a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return handled; 362a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 363a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 364a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 365a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) { 366a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell super.requestDisallowInterceptTouchEvent(disallowIntercept); 367a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (disallowIntercept) { 3685cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell resetTouchBehaviors(); 369a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 370a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 371a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 372a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private int getKeyline(int index) { 373a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mKeylines == null) { 374a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Log.e(TAG, "No keylines defined for " + this + " - attempted index lookup " + index); 375a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return 0; 376a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 377a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 378a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (index < 0 || index >= mKeylines.length) { 379a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Log.e(TAG, "Keyline index " + index + " out of range for " + this); 380a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return 0; 381a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 382a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 383a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return mKeylines[index]; 384a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 385a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 386a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell static Behavior parseBehavior(Context context, AttributeSet attrs, String name) { 387a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (TextUtils.isEmpty(name)) { 388a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return null; 389a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 390a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 391a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final String fullName; 392a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (name.startsWith(".")) { 393a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Relative to the app package. Prepend the app package name. 394a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell fullName = context.getPackageName() + name; 395a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else if (name.indexOf('.') >= 0) { 396a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Fully qualified package name. 397a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell fullName = name; 398a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else { 399a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Assume stock behavior in this package. 400a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell fullName = WIDGET_PACKAGE_NAME + '.' + name; 401a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 402a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 403a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell try { 404a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Map<String, Constructor<Behavior>> constructors = sConstructors.get(); 405a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (constructors == null) { 406a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell constructors = new HashMap<>(); 407a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell sConstructors.set(constructors); 408a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 409a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Constructor<Behavior> c = constructors.get(fullName); 410a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (c == null) { 411a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Class<Behavior> clazz = (Class<Behavior>) Class.forName(fullName, true, 412a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell context.getClassLoader()); 413a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell c = clazz.getConstructor(CONSTRUCTOR_PARAMS); 414878384f1e6de7bd9196958224ced1ecfca3be6a7Chris Banes c.setAccessible(true); 415a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell constructors.put(fullName, c); 416a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 417a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return c.newInstance(context, attrs); 418a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } catch (Exception e) { 419a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell throw new RuntimeException("Could not inflate Behavior subclass " + fullName, e); 420a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 421a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 422a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 423a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell LayoutParams getResolvedLayoutParams(View child) { 424a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams result = (LayoutParams) child.getLayoutParams(); 425a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (!result.mBehaviorResolved) { 42642058bc54bdb89b9c9429bf6cbd3260787cf0523Adam Powell Class<?> childClass = child.getClass(); 42742058bc54bdb89b9c9429bf6cbd3260787cf0523Adam Powell DefaultBehavior defaultBehavior = null; 42842058bc54bdb89b9c9429bf6cbd3260787cf0523Adam Powell while (childClass != null && 42942058bc54bdb89b9c9429bf6cbd3260787cf0523Adam Powell (defaultBehavior = childClass.getAnnotation(DefaultBehavior.class)) == null) { 43042058bc54bdb89b9c9429bf6cbd3260787cf0523Adam Powell childClass = childClass.getSuperclass(); 43142058bc54bdb89b9c9429bf6cbd3260787cf0523Adam Powell } 432a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (defaultBehavior != null) { 433a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell try { 434a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell result.setBehavior(defaultBehavior.value().newInstance()); 435a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } catch (Exception e) { 436a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Log.e(TAG, "Default behavior class " + defaultBehavior.value().getName() + 437a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell " could not be instantiated. Did you forget a default constructor?", e); 438a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 439a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 440a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell result.mBehaviorResolved = true; 441a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 442a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return result; 443a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 444a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 445a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private void prepareChildren() { 446a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childCount = getChildCount(); 447a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 448a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean resortRequired = mDependencySortedChildren.size() != childCount; 449a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 450a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int i = 0; i < childCount; i++) { 451a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final View child = getChildAt(i); 452a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = getResolvedLayoutParams(child); 453a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (!resortRequired && lp.isDirty(this, child)) { 454a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell resortRequired = true; 455a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 456a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell lp.findAnchorView(this, child); 457a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 458a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 459a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (resortRequired) { 460a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mDependencySortedChildren.clear(); 461a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int i = 0; i < childCount; i++) { 462a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mDependencySortedChildren.add(getChildAt(i)); 463a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 464a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Collections.sort(mDependencySortedChildren, mLayoutDependencyComparator); 465a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 466a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 467a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 468a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 469a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Retrieve the transformed bounding rect of an arbitrary descendant view. 470a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * This does not need to be a direct child. 471a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 472a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param descendant descendant view to reference 473a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param out rect to set to the bounds of the descendant view 474a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 475a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void getDescendantRect(View descendant, Rect out) { 476a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes ViewGroupUtils.getDescendantRect(this, descendant, out); 477a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 478a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 479a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 480a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell protected int getSuggestedMinimumWidth() { 481a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return Math.max(super.getSuggestedMinimumWidth(), getPaddingLeft() + getPaddingRight()); 482a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 483a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 484a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 485a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell protected int getSuggestedMinimumHeight() { 486a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return Math.max(super.getSuggestedMinimumHeight(), getPaddingTop() + getPaddingBottom()); 487a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 488a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 489a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 490a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Called to measure each individual child view unless a 491a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link CoordinatorLayout.Behavior Behavior} is present. The Behavior may choose to delegate 492a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * child measurement to this method. 493a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 494a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child to measure 495a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parentWidthMeasureSpec the width requirements for this view 496a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param widthUsed extra space that has been used up by the parent 497a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * horizontally (possibly by other children of the parent) 498a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parentHeightMeasureSpec the height requirements for this view 499a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param heightUsed extra space that has been used up by the parent 500a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * vertically (possibly by other children of the parent) 501a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 502a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public void onMeasureChild(View child, int parentWidthMeasureSpec, int widthUsed, 503a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int parentHeightMeasureSpec, int heightUsed) { 504a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell measureChildWithMargins(child, parentWidthMeasureSpec, widthUsed, 505a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell parentHeightMeasureSpec, heightUsed); 506a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 507a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 508a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 509a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 510a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell prepareChildren(); 511a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell ensurePreDrawListener(); 512a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 513a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int paddingLeft = getPaddingLeft(); 514a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int paddingTop = getPaddingTop(); 515a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int paddingRight = getPaddingRight(); 516a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int paddingBottom = getPaddingBottom(); 517a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int layoutDirection = ViewCompat.getLayoutDirection(this); 518a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final boolean isRtl = layoutDirection == ViewCompat.LAYOUT_DIRECTION_RTL; 519a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int widthMode = MeasureSpec.getMode(widthMeasureSpec); 520a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int widthSize = MeasureSpec.getSize(widthMeasureSpec); 521a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 522a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int widthPadding = paddingLeft + paddingRight; 523a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int heightPadding = paddingTop + paddingBottom; 524a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int widthUsed = getSuggestedMinimumWidth(); 525a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int heightUsed = getSuggestedMinimumHeight(); 526a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int childState = 0; 527a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 528a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childCount = mDependencySortedChildren.size(); 529a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int i = 0; i < childCount; i++) { 530a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final View child = mDependencySortedChildren.get(i); 531a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 532a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 533a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int keylineWidthUsed = 0; 534a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (lp.keyline >= 0 && widthMode != MeasureSpec.UNSPECIFIED) { 535a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int keylinePos = getKeyline(lp.keyline); 536a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int keylineGravity = GravityCompat.getAbsoluteGravity( 537a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell resolveKeylineGravity(lp.gravity), layoutDirection) 538a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell & Gravity.HORIZONTAL_GRAVITY_MASK; 539a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if ((keylineGravity == Gravity.LEFT && !isRtl) 540a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell || (keylineGravity == Gravity.RIGHT && isRtl)) { 541a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell keylineWidthUsed = Math.max(0, widthSize - paddingRight - keylinePos); 542a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else if ((keylineGravity == Gravity.RIGHT && !isRtl) 543a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell || (keylineGravity == Gravity.LEFT && isRtl)) { 544a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell keylineWidthUsed = Math.max(0, keylinePos - paddingLeft); 545a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 546a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 547a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 548a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Behavior b = lp.getBehavior(); 549a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (b == null || !b.onMeasureChild(this, child, widthMeasureSpec, keylineWidthUsed, 550a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell heightMeasureSpec, 0)) { 551a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell onMeasureChild(child, widthMeasureSpec, keylineWidthUsed, 552a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell heightMeasureSpec, 0); 553a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 554a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 555a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell widthUsed = Math.max(widthUsed, widthPadding + child.getMeasuredWidth() + 556a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell lp.leftMargin + lp.rightMargin); 557a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 558a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell heightUsed = Math.max(heightUsed, heightPadding + child.getMeasuredHeight() + 559a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell lp.topMargin + lp.bottomMargin); 560a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell childState = ViewCompat.combineMeasuredStates(childState, 561a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell ViewCompat.getMeasuredState(child)); 562a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 563a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 564a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int width = ViewCompat.resolveSizeAndState(widthUsed, widthMeasureSpec, 565a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell childState & ViewCompat.MEASURED_STATE_MASK); 566a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int height = ViewCompat.resolveSizeAndState(heightUsed, heightMeasureSpec, 567a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell childState << ViewCompat.MEASURED_HEIGHT_STATE_SHIFT); 568a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell setMeasuredDimension(width, height); 569a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 570a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 571a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 572a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Called to lay out each individual child view unless a 573a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link CoordinatorLayout.Behavior Behavior} is present. The Behavior may choose to 574a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * delegate child measurement to this method. 575a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 576a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child view to lay out 577a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param layoutDirection the resolved layout direction for the CoordinatorLayout, such as 578a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link ViewCompat#LAYOUT_DIRECTION_LTR} or 579a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link ViewCompat#LAYOUT_DIRECTION_RTL}. 580a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 581a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public void onLayoutChild(View child, int layoutDirection) { 582a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 583a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (lp.checkAnchorChanged()) { 584a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell throw new IllegalStateException("An anchor may not be changed after CoordinatorLayout" 585a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell + " measurement begins before layout is complete."); 586a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 587a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (lp.mAnchorView != null) { 588a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell layoutChildWithAnchor(child, lp.mAnchorView, layoutDirection); 589a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else if (lp.keyline >= 0) { 590a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell layoutChildWithKeyline(child, lp.keyline, layoutDirection); 591a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else { 592a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell layoutChild(child, layoutDirection); 593a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 594a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 595a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 596a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 597a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell protected void onLayout(boolean changed, int l, int t, int r, int b) { 598a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int layoutDirection = ViewCompat.getLayoutDirection(this); 599a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childCount = mDependencySortedChildren.size(); 600a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int i = 0; i < childCount; i++) { 601a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final View child = mDependencySortedChildren.get(i); 602a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 603a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Behavior behavior = lp.getBehavior(); 604a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 605a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (behavior == null || !behavior.onLayoutChild(this, child, layoutDirection)) { 606a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell onLayoutChild(child, layoutDirection); 607a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 608a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 609a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 610a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 611a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 612a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Mark the last known child position rect for the given child view. 613a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * This will be used when checking if a child view's position has changed between frames. 614a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * The rect used here should be one returned by 615a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link #getChildRect(android.view.View, boolean, android.graphics.Rect)}, with translation 616a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * disabled. 617a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 618a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child view to set for 619a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param r rect to set 620a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 621a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void recordLastChildRect(View child, Rect r) { 622a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 623a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell lp.setLastChildRect(r); 624a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 625a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 626a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 627a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Get the last known child rect recorded by 628a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link #recordLastChildRect(android.view.View, android.graphics.Rect)}. 629a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 630a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child view to retrieve from 631a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param out rect to set to the outpur values 632a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 633a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void getLastChildRect(View child, Rect out) { 634a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 635a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell out.set(lp.getLastChildRect()); 636a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 637a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 638a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 639a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Get the position rect for the given child. If the child has currently requested layout 640a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * or has a visibility of GONE. 641a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 642a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child view to check 643a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param transform true to include transformation in the output rect, false to 644a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * only account for the base position 645a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param out rect to set to the output values 646a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 647a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void getChildRect(View child, boolean transform, Rect out) { 648a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (child.isLayoutRequested() || child.getVisibility() == View.GONE) { 649a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell out.set(0, 0, 0, 0); 650a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return; 651a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 652a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (transform) { 653a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getDescendantRect(child, out); 654a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else { 655a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell out.set(child.getLeft(), child.getTop(), child.getRight(), child.getBottom()); 656a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 657a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 658a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 659a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 660a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Calculate the desired child rect relative to an anchor rect, respecting both 661a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * gravity and anchorGravity. 662a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 663a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child view to calculate a rect for 664a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param layoutDirection the desired layout direction for the CoordinatorLayout 665a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param anchorRect rect in CoordinatorLayout coordinates of the anchor view area 666a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param out rect to set to the output values 667a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 668a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void getDesiredAnchoredChildRect(View child, int layoutDirection, Rect anchorRect, Rect out) { 669a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 670a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int absGravity = GravityCompat.getAbsoluteGravity( 671a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell resolveAnchoredChildGravity(lp.gravity), layoutDirection); 672a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int absAnchorGravity = GravityCompat.getAbsoluteGravity( 673a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell resolveGravity(lp.anchorGravity), 674a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell layoutDirection); 675a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 676a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int hgrav = absGravity & Gravity.HORIZONTAL_GRAVITY_MASK; 677a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int vgrav = absGravity & Gravity.VERTICAL_GRAVITY_MASK; 678a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int anchorHgrav = absAnchorGravity & Gravity.HORIZONTAL_GRAVITY_MASK; 679a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int anchorVgrav = absAnchorGravity & Gravity.VERTICAL_GRAVITY_MASK; 680a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 681a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childWidth = child.getMeasuredWidth(); 682a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childHeight = child.getMeasuredHeight(); 683a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 684a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int left; 685a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int top; 686a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 687a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Align to the anchor 688a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell switch (anchorHgrav) { 689a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell default: 690a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.LEFT: 691a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell left = anchorRect.left; 692a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 693a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.RIGHT: 694a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell left = anchorRect.right - childWidth; 695a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 696a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.CENTER_HORIZONTAL: 697a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell left = anchorRect.left + (anchorRect.width() - childWidth) / 2; 698a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 699a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 700a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 701a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell switch (anchorVgrav) { 702a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell default: 703a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.TOP: 704a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell top = anchorRect.top; 705a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 706a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.BOTTOM: 707a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell top = anchorRect.bottom - childHeight; 708a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 709a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.CENTER_VERTICAL: 710a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell top = anchorRect.top + (anchorRect.height() - childHeight) / 2; 711a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 712a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 713a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 714a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Offset by the child view's gravity itself 715a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell switch (hgrav) { 716a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell default: 717a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.LEFT: 718a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Do nothing, we're already in position. 719a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 720a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.RIGHT: 721a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell left += childWidth; 722a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 723a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.CENTER_HORIZONTAL: 724a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell left += childWidth / 2; 725a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 726a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 727a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 728a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell switch (vgrav) { 729a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell default: 730a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.TOP: 731a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Do nothing, we're already in position. 732a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 733a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.BOTTOM: 734a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell top += childHeight; 735a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 736a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.CENTER_VERTICAL: 737a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell top += childHeight / 2; 738a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 739a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 740a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 741a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int width = getWidth(); 742a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int height = getHeight(); 743a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 744a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Obey margins and padding 745a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell left = Math.max(getPaddingLeft() + lp.leftMargin, 746a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Math.min(left, 747a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell width - getPaddingRight() - childWidth - lp.rightMargin)); 748a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell top = Math.max(getPaddingTop() + lp.topMargin, 749a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Math.min(top, 750a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell height - getPaddingBottom() - childHeight - lp.bottomMargin)); 751a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 752a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell out.set(left, top, left + childWidth, top + childHeight); 753a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 754a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 755a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 756a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * CORE ASSUMPTION: anchor has been laid out by the time this is called for a given child view. 757a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 758a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child to lay out 759a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param anchor view to anchor child relative to; already laid out. 760a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param layoutDirection ViewCompat constant for layout direction 761a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 762a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private void layoutChildWithAnchor(View child, View anchor, int layoutDirection) { 763a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 764a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 765a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Rect anchorRect = mTempRect1; 766a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Rect childRect = mTempRect2; 767a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getDescendantRect(anchor, anchorRect); 768a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getDesiredAnchoredChildRect(child, layoutDirection, anchorRect, childRect); 769a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 770a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell child.layout(childRect.left, childRect.top, childRect.right, childRect.bottom); 771a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 772a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 773a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 774a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Lay out a child view with respect to a keyline. 775a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 776a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>The keyline represents a horizontal offset from the unpadded starting edge of 777a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * the CoordinatorLayout. The child's gravity will affect how it is positioned with 778a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * respect to the keyline.</p> 779a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 780a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child to lay out 781a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param keyline offset from the starting edge in pixels of the keyline to align with 782a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param layoutDirection ViewCompat constant for layout direction 783a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 784a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private void layoutChildWithKeyline(View child, int keyline, int layoutDirection) { 785a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 786a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int absGravity = GravityCompat.getAbsoluteGravity( 787a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell resolveKeylineGravity(lp.gravity), layoutDirection); 788a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 789a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int hgrav = absGravity & Gravity.HORIZONTAL_GRAVITY_MASK; 790a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int vgrav = absGravity & Gravity.VERTICAL_GRAVITY_MASK; 791a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int width = getWidth(); 792a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int height = getHeight(); 793a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childWidth = child.getMeasuredWidth(); 794a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childHeight = child.getMeasuredHeight(); 795a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 796a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (layoutDirection == ViewCompat.LAYOUT_DIRECTION_RTL) { 797a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell keyline = width - keyline; 798a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 799a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 800a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int left = getKeyline(keyline) - childWidth; 801a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int top = 0; 802a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 803a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell switch (hgrav) { 804a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell default: 805a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.LEFT: 806a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Nothing to do. 807a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 808a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.RIGHT: 809a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell left += childWidth; 810a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 811a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.CENTER_HORIZONTAL: 812a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell left += childWidth / 2; 813a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 814a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 815a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 816a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell switch (vgrav) { 817a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell default: 818a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.TOP: 819a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Do nothing, we're already in position. 820a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 821a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.BOTTOM: 822a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell top += childHeight; 823a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 824a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.CENTER_VERTICAL: 825a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell top += childHeight / 2; 826a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 827a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 828a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 829a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Obey margins and padding 830a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell left = Math.max(getPaddingLeft() + lp.leftMargin, 831a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Math.min(left, 832a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell width - getPaddingRight() - childWidth - lp.rightMargin)); 833a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell top = Math.max(getPaddingTop() + lp.topMargin, 834a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Math.min(top, 835a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell height - getPaddingBottom() - childHeight - lp.bottomMargin)); 836a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 837a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell child.layout(left, top, left + childWidth, top + childHeight); 838a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 839a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 840a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 841a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Lay out a child view with no special handling. This will position the child as 842a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * if it were within a FrameLayout or similar simple frame. 843a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 844a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child view to lay out 845a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param layoutDirection ViewCompat constant for the desired layout direction 846a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 847a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private void layoutChild(View child, int layoutDirection) { 848a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 849a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Rect parent = mTempRect1; 850a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell parent.set(getPaddingLeft() + lp.leftMargin, 851a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getPaddingTop() + lp.topMargin, 852a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getWidth() - getPaddingRight() - lp.rightMargin, 853a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getHeight() - getPaddingBottom() - lp.bottomMargin); 854a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Rect out = mTempRect2; 855a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell GravityCompat.apply(resolveGravity(lp.gravity), child.getMeasuredWidth(), 856a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell child.getMeasuredHeight(), parent, out, layoutDirection); 857a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell child.layout(out.left, out.top, out.right, out.bottom); 858a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 859a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 860a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 861a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Return the given gravity value or the default if the passed value is NO_GRAVITY. 862a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * This should be used for children that are not anchored to another view or a keyline. 863a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 864a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private static int resolveGravity(int gravity) { 865a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return gravity == Gravity.NO_GRAVITY ? GravityCompat.START | Gravity.TOP : gravity; 866a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 867a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 868a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 869a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Return the given gravity value or the default if the passed value is NO_GRAVITY. 870a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * This should be used for children that are positioned relative to a keyline. 871a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 872a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private static int resolveKeylineGravity(int gravity) { 873a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return gravity == Gravity.NO_GRAVITY ? GravityCompat.END | Gravity.TOP : gravity; 874a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 875a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 876a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 877a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Return the given gravity value or the default if the passed value is NO_GRAVITY. 878a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * This should be used for children that are anchored to another view. 879a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 880a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private static int resolveAnchoredChildGravity(int gravity) { 881a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return gravity == Gravity.NO_GRAVITY ? Gravity.CENTER : gravity; 882a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 883a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 884a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 885a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell protected boolean drawChild(Canvas canvas, View child, long drawingTime) { 886a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 887a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (lp.mBehavior != null && lp.mBehavior.getScrimOpacity(this, child) > 0.f) { 888a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mScrimPaint == null) { 889a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mScrimPaint = new Paint(); 890a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 891a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mScrimPaint.setColor(lp.mBehavior.getScrimColor(this, child)); 892a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 893a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // TODO: Set the clip appropriately to avoid unnecessary overdraw. 894a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell canvas.drawRect(getPaddingLeft(), getPaddingTop(), 895a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getWidth() - getPaddingRight(), getHeight() - getPaddingBottom(), mScrimPaint); 896a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 897a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return super.drawChild(canvas, child, drawingTime); 898a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 899a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 900a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 901a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * Dispatch any dependent view changes to the relevant {@link Behavior} instances. 902a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * 903a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * Usually run as part of the pre-draw step when at least one child view has a reported 904a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * dependency on another view. This allows CoordinatorLayout to account for layout 905a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * changes and animations that occur outside of the normal layout pass. 906a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 907a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * It can also be ran as part of the nested scrolling dispatch to ensure that any offsetting 908a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * is completed within the correct coordinate window. 909a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * 910a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * The offsetting behavior implemented here does not store the computed offset in 911a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * the LayoutParams; instead it expects that the layout process will always reconstruct 912a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * the proper positioning. 913a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * 914a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * @param fromNestedScroll true if this is being called from one of the nested scroll methods, 915a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * false if run as part of the pre-draw step. 916a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 917a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes void dispatchOnDependentViewChanged(final boolean fromNestedScroll) { 918a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int layoutDirection = ViewCompat.getLayoutDirection(this); 919a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childCount = mDependencySortedChildren.size(); 920a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int i = 0; i < childCount; i++) { 921a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final View child = mDependencySortedChildren.get(i); 922a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 923a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 924a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Check child views before for anchor 925a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int j = 0; j < i; j++) { 926a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final View checkChild = mDependencySortedChildren.get(j); 927a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 928a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (lp.mAnchorDirectChild == checkChild) { 929a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell offsetChildToAnchor(child, layoutDirection); 930a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 931a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 932a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 933a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Did it change? if not continue 934a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Rect oldRect = mTempRect1; 935a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Rect newRect = mTempRect2; 936a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getLastChildRect(child, oldRect); 937b7f9224b1495db47eb8fd813b5912250e900770aChris Banes getChildRect(child, true, newRect); 938a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (oldRect.equals(newRect)) { 939a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell continue; 940a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 941a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell recordLastChildRect(child, newRect); 942a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 943a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Update any behavior-dependent views for the change 944a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int j = i + 1; j < childCount; j++) { 945a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final View checkChild = mDependencySortedChildren.get(j); 946a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams checkLp = (LayoutParams) checkChild.getLayoutParams(); 947a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Behavior b = checkLp.getBehavior(); 948a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 949a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (b != null && b.layoutDependsOn(this, checkChild, child)) { 950a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes if (!fromNestedScroll && checkLp.getChangedAfterNestedScroll()) { 951a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes // If this is not from a nested scroll and we have already been changed 952a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes // from a nested scroll, skip the dispatch and reset the flag 953a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes checkLp.resetChangedAfterNestedScroll(); 954a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes continue; 955a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 956a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 957a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes final boolean handled = b.onDependentViewChanged(this, checkChild, child); 958a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 959a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes if (fromNestedScroll) { 960a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes // If this is from a nested scroll, set the flag so that we may skip 961a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes // any resulting onPreDraw dispatch (if needed) 962a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes checkLp.setChangedAfterNestedScroll(handled); 963a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 964a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 965a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 966a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 967a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 968a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 969a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes /** 970a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * Allows the caller to manually dispatch 971a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * {@link Behavior#onDependentViewChanged(CoordinatorLayout, View, View)} to the associated 972a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * {@link Behavior} instances of views which depend on the provided {@link View}. 973a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * 974a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * <p>You should not normally need to call this method as the it will be automatically done 975a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * when the view has changed. 976a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * 977a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * @param view the View to find dependents of to dispatch the call. 978a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes */ 979a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes public void dispatchDependentViewsChanged(View view) { 980a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes final int childCount = mDependencySortedChildren.size(); 981a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes boolean viewSeen = false; 982a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes for (int i = 0; i < childCount; i++) { 983a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes final View child = mDependencySortedChildren.get(i); 984a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes if (child == view) { 985a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes // We've seen our view, which means that any Views after this could be dependent 986a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes viewSeen = true; 987a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes continue; 988a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 989a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes if (viewSeen) { 990a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams) 991a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes child.getLayoutParams(); 992a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes CoordinatorLayout.Behavior b = lp.getBehavior(); 993a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes if (b != null && lp.dependsOn(this, child, view)) { 994a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes b.onDependentViewChanged(this, child, view); 995a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 996a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 997a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 998a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 999a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1000a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1001a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * Returns the list of views which the provided view depends on. Do not store this list as it's 1002a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * contents may not be valid beyond the caller. 1003a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * 1004a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * @param child the view to find dependencies for. 1005a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * 1006a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * @return the list of views which {@code child} depends on. 1007a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes */ 1008a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes public List<View> getDependencies(View child) { 1009a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes // TODO The result of this is probably a good candidate for caching 1010a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 1011a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 1012a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes final List<View> list = mTempDependenciesList; 1013a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes list.clear(); 1014a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 1015a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes final int childCount = getChildCount(); 1016a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes for (int i = 0; i < childCount; i++) { 1017a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes final View other = getChildAt(i); 1018a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes if (other == child) { 1019a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes continue; 1020a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1021a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes if (lp.dependsOn(this, child, other)) { 1022a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes list.add(other); 1023a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1024a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1025a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 1026a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes return list; 1027a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1028a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 1029a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes /** 1030a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Add or remove the pre-draw listener as necessary. 1031a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1032a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void ensurePreDrawListener() { 1033a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean hasDependencies = false; 1034a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childCount = getChildCount(); 1035a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int i = 0; i < childCount; i++) { 1036a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final View child = getChildAt(i); 1037a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (hasDependencies(child)) { 1038a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell hasDependencies = true; 1039a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 1040a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1041a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1042a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1043a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (hasDependencies != mNeedsPreDrawListener) { 1044a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (hasDependencies) { 1045a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell addPreDrawListener(); 1046a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else { 1047a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell removePreDrawListener(); 1048a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1049a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1050a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1051a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1052a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1053a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Check if the given child has any layout dependencies on other child views. 1054a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1055a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean hasDependencies(View child) { 1056a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 1057a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (lp.mAnchorView != null) { 1058a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return true; 1059a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1060a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1061a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childCount = getChildCount(); 1062a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int i = 0; i < childCount; i++) { 1063a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final View other = getChildAt(i); 1064a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (other == child) { 1065a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell continue; 1066a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1067a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (lp.dependsOn(this, child, other)) { 1068a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return true; 1069a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1070a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1071a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return false; 1072a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1073a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1074a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1075a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Add the pre-draw listener if we're attached to a window and mark that we currently 1076a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * need it when attached. 1077a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1078a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void addPreDrawListener() { 1079a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mIsAttachedToWindow) { 1080a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Add the listener 1081a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mOnPreDrawListener == null) { 1082a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mOnPreDrawListener = new OnPreDrawListener(); 1083a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1084a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final ViewTreeObserver vto = getViewTreeObserver(); 1085a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell vto.addOnPreDrawListener(mOnPreDrawListener); 1086a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1087a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1088a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Record that we need the listener regardless of whether or not we're attached. 1089a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // We'll add the real listener when we become attached. 1090a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mNeedsPreDrawListener = true; 1091a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1092a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1093a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1094a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Remove the pre-draw listener if we're attached to a window and mark that we currently 1095a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * do not need it when attached. 1096a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1097a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void removePreDrawListener() { 1098a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mIsAttachedToWindow) { 1099a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mOnPreDrawListener != null) { 1100a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final ViewTreeObserver vto = getViewTreeObserver(); 1101a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell vto.removeOnPreDrawListener(mOnPreDrawListener); 1102a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1103a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1104a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mNeedsPreDrawListener = false; 1105a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1106a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1107a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1108a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Adjust the child left, top, right, bottom rect to the correct anchor view position, 1109a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * respecting gravity and anchor gravity. 1110a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1111a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Note that child translation properties are ignored in this process, allowing children 1112a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * to be animated away from their anchor. However, if the anchor view is animated, 1113a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * the child will be offset to match the anchor's translated position. 1114a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1115a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void offsetChildToAnchor(View child, int layoutDirection) { 1116a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 1117a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (lp.mAnchorView != null) { 1118a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Rect anchorRect = mTempRect1; 1119a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Rect childRect = mTempRect2; 1120a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Rect desiredChildRect = mTempRect3; 1121a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1122a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getDescendantRect(lp.mAnchorView, anchorRect); 1123a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getChildRect(child, false, childRect); 1124a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getDesiredAnchoredChildRect(child, layoutDirection, anchorRect, desiredChildRect); 1125a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1126a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int dx = desiredChildRect.left - childRect.left; 1127a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int dy = desiredChildRect.top - childRect.top; 1128a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1129a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (dx != 0) { 1130a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell child.offsetLeftAndRight(dx); 1131a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1132a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (dy != 0) { 1133a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell child.offsetTopAndBottom(dy); 1134a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1135a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 1136a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes if (dx != 0 || dy != 0) { 1137a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes // If we have needed to move, make sure to notify the child's Behavior 1138a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes final Behavior b = lp.getBehavior(); 1139a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes if (b != null) { 1140a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes b.onDependentViewChanged(this, child, lp.mAnchorView); 1141a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1142a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1143a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1144a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1145a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1146a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1147a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Check if a given point in the CoordinatorLayout's coordinates are within the view bounds 1148a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * of the given direct child view. 1149a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1150a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child view to test 1151a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param x X coordinate to test, in the CoordinatorLayout's coordinate system 1152a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param y Y coordinate to test, in the CoordinatorLayout's coordinate system 1153a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true if the point is within the child view's bounds, false otherwise 1154a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1155a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean isPointInChildBounds(View child, int x, int y) { 1156a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Rect r = mTempRect1; 1157a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getDescendantRect(child, r); 1158a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return r.contains(x, y); 1159a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1160a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1161b7f9224b1495db47eb8fd813b5912250e900770aChris Banes /** 1162b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * Check whether two views overlap each other. The views need to be descendants of this 1163b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * {@link CoordinatorLayout} in the view hierarchy. 1164b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * 1165b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * @param first first child view to test 1166b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * @param second second child view to test 1167b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * @return true if both views are visible and overlap each other 1168b7f9224b1495db47eb8fd813b5912250e900770aChris Banes */ 1169b7f9224b1495db47eb8fd813b5912250e900770aChris Banes public boolean doViewsOverlap(View first, View second) { 1170b7f9224b1495db47eb8fd813b5912250e900770aChris Banes if (first.getVisibility() == VISIBLE && second.getVisibility() == VISIBLE) { 1171b7f9224b1495db47eb8fd813b5912250e900770aChris Banes final Rect firstRect = mTempRect1; 1172b7f9224b1495db47eb8fd813b5912250e900770aChris Banes getChildRect(first, first.getParent() != this, firstRect); 1173b7f9224b1495db47eb8fd813b5912250e900770aChris Banes final Rect secondRect = mTempRect2; 1174b7f9224b1495db47eb8fd813b5912250e900770aChris Banes getChildRect(second, second.getParent() != this, secondRect); 1175b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 1176b7f9224b1495db47eb8fd813b5912250e900770aChris Banes return !(firstRect.left > secondRect.right || firstRect.top > secondRect.bottom 1177b7f9224b1495db47eb8fd813b5912250e900770aChris Banes || firstRect.right < secondRect.left || firstRect.bottom < secondRect.top); 1178b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 1179b7f9224b1495db47eb8fd813b5912250e900770aChris Banes return false; 1180b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 1181b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 1182a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 1183a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public LayoutParams generateLayoutParams(AttributeSet attrs) { 1184a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return new LayoutParams(getContext(), attrs); 1185a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1186a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1187a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 1188a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { 1189a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (p instanceof LayoutParams) { 1190a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return new LayoutParams((LayoutParams) p); 1191a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else if (p instanceof MarginLayoutParams) { 1192a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return new LayoutParams((MarginLayoutParams) p); 1193a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1194a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return new LayoutParams(p); 1195a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1196a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1197a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 1198a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell protected LayoutParams generateDefaultLayoutParams() { 1199a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); 1200a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1201a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1202a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 1203a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { 1204a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return p instanceof LayoutParams && super.checkLayoutParams(p); 1205a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1206a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1207a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) { 12085cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell boolean handled = false; 12095cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 12105cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final int childCount = getChildCount(); 12115cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell for (int i = 0; i < childCount; i++) { 12125cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final View view = getChildAt(i); 12135cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final LayoutParams lp = (LayoutParams) view.getLayoutParams(); 12145cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final Behavior viewBehavior = lp.getBehavior(); 12155cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (viewBehavior != null) { 12165cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final boolean accepted = viewBehavior.onStartNestedScroll(this, view, child, target, 12175cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell nestedScrollAxes); 12185cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell handled |= accepted; 12195cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 12205cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell lp.acceptNestedScroll(accepted); 12215cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } else { 12225cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell lp.acceptNestedScroll(false); 12235cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 12245cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 12255cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell return handled; 1226a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1227a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1228a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public void onNestedScrollAccepted(View child, View target, int nestedScrollAxes) { 1229a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mNestedScrollingParentHelper.onNestedScrollAccepted(child, target, nestedScrollAxes); 12305cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell mNestedScrollingDirectChild = child; 12315cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell mNestedScrollingTarget = target; 12325cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 12335cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final int childCount = getChildCount(); 12345cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell for (int i = 0; i < childCount; i++) { 12355cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final View view = getChildAt(i); 12365cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final LayoutParams lp = (LayoutParams) view.getLayoutParams(); 12375cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (!lp.isNestedScrollAccepted()) { 12385cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell continue; 12395cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 12405cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 12415cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final Behavior viewBehavior = lp.getBehavior(); 12425cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (viewBehavior != null) { 12435cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell viewBehavior.onNestedScrollAccepted(this, view, child, target, nestedScrollAxes); 12445cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 12455cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 1246a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1247a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1248a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public void onStopNestedScroll(View target) { 1249a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mNestedScrollingParentHelper.onStopNestedScroll(target); 12505cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 12515cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final int childCount = getChildCount(); 12525cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell for (int i = 0; i < childCount; i++) { 12535cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final View view = getChildAt(i); 12545cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final LayoutParams lp = (LayoutParams) view.getLayoutParams(); 12555cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (!lp.isNestedScrollAccepted()) { 12565cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell continue; 12575cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 12585cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 12595cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final Behavior viewBehavior = lp.getBehavior(); 12605cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (viewBehavior != null) { 12615cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell viewBehavior.onStopNestedScroll(this, view, target); 12625cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 12635cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell lp.resetNestedScroll(); 1264a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes lp.resetChangedAfterNestedScroll(); 12655cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 12665cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 12675cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell mNestedScrollingDirectChild = null; 12685cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell mNestedScrollingTarget = null; 1269a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1270a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1271a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public void onNestedScroll(View target, int dxConsumed, int dyConsumed, 1272a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int dxUnconsumed, int dyUnconsumed) { 12735cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final int childCount = getChildCount(); 1274a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes boolean accepted = false; 1275a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 12765cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell for (int i = 0; i < childCount; i++) { 12775cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final View view = getChildAt(i); 12785cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final LayoutParams lp = (LayoutParams) view.getLayoutParams(); 12795cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (!lp.isNestedScrollAccepted()) { 12805cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell continue; 12815cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 12825cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 12835cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final Behavior viewBehavior = lp.getBehavior(); 12845cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (viewBehavior != null) { 12855cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell viewBehavior.onNestedScroll(this, view, target, dxConsumed, dyConsumed, 12865cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell dxUnconsumed, dyUnconsumed); 1287a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes accepted = true; 12885cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 12895cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 1290a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 1291a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes if (accepted) { 1292a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes dispatchOnDependentViewChanged(true); 1293a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1294a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1295a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1296a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) { 12975cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell int xConsumed = 0; 12985cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell int yConsumed = 0; 1299a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes boolean accepted = false; 13005cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 13015cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final int childCount = getChildCount(); 13025cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell for (int i = 0; i < childCount; i++) { 13035cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final View view = getChildAt(i); 13045cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final LayoutParams lp = (LayoutParams) view.getLayoutParams(); 13055cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (!lp.isNestedScrollAccepted()) { 13065cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell continue; 13075cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 13085cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 13095cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final Behavior viewBehavior = lp.getBehavior(); 13105cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (viewBehavior != null) { 13115cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell mTempIntPair[0] = mTempIntPair[1] = 0; 13125cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell viewBehavior.onNestedPreScroll(this, view, target, dx, dy, mTempIntPair); 13135cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 13145cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell xConsumed = dx > 0 ? Math.max(xConsumed, mTempIntPair[0]) 13155cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell : Math.min(xConsumed, mTempIntPair[0]); 13165cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell yConsumed = dy > 0 ? Math.max(yConsumed, mTempIntPair[1]) 13175cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell : Math.min(yConsumed, mTempIntPair[1]); 1318a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 1319a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes accepted = true; 13205cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 13215cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 13225cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 13235cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell consumed[0] = xConsumed; 13245cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell consumed[1] = yConsumed; 1325a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 1326a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes if (accepted) { 1327a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes dispatchOnDependentViewChanged(true); 1328a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1329a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1330a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1331a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) { 13325cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell boolean handled = false; 13335cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 13345cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final int childCount = getChildCount(); 13355cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell for (int i = 0; i < childCount; i++) { 13365cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final View view = getChildAt(i); 13375cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final LayoutParams lp = (LayoutParams) view.getLayoutParams(); 13385cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (!lp.isNestedScrollAccepted()) { 13395cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell continue; 13405cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 13415cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 13425cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final Behavior viewBehavior = lp.getBehavior(); 13435cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (viewBehavior != null) { 13445cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell handled |= viewBehavior.onNestedFling(this, view, target, velocityX, velocityY, 13455cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell consumed); 13465cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 13475cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 1348a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes if (handled) { 1349a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes dispatchOnDependentViewChanged(true); 1350a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 13515cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell return handled; 1352a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1353a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1354a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean onNestedPreFling(View target, float velocityX, float velocityY) { 13555cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell boolean handled = false; 13565cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 13575cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final int childCount = getChildCount(); 13585cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell for (int i = 0; i < childCount; i++) { 13595cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final View view = getChildAt(i); 13605cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final LayoutParams lp = (LayoutParams) view.getLayoutParams(); 13615cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (!lp.isNestedScrollAccepted()) { 13625cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell continue; 13635cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 13645cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 13655cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final Behavior viewBehavior = lp.getBehavior(); 13665cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (viewBehavior != null) { 13675cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell handled |= viewBehavior.onNestedPreFling(this, view, target, velocityX, velocityY); 13685cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 13695cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 13705cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell return handled; 1371a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1372a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1373a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public int getNestedScrollAxes() { 1374a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return mNestedScrollingParentHelper.getNestedScrollAxes(); 1375a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1376a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1377a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell class OnPreDrawListener implements ViewTreeObserver.OnPreDrawListener { 1378a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 1379a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean onPreDraw() { 1380a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes dispatchOnDependentViewChanged(false); 1381a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return true; 1382a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1383a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1384a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1385a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1386a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Sorts child views with higher Z values to the beginning of a collection. 1387a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1388a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell static class ViewElevationComparator implements Comparator<View> { 1389a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 1390a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public int compare(View lhs, View rhs) { 1391a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final float lz = ViewCompat.getZ(lhs); 1392a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final float rz = ViewCompat.getZ(rhs); 1393a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (lz > rz) { 1394a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return -1; 1395a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else if (lz < rz) { 1396a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return 1; 1397a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1398a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return 0; 1399a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1400a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1401a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1402a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1403a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Defines the default {@link Behavior} of a {@link View} class. 1404a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1405a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>When writing a custom view, use this annotation to define the default behavior 1406a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * when used as a direct child of an {@link CoordinatorLayout}. The default behavior 1407a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * can be overridden using {@link LayoutParams#setBehavior}.</p> 1408a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1409a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>Example: <code>@DefaultBehavior(MyBehavior.class)</code></p> 1410a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1411a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Retention(RetentionPolicy.RUNTIME) 1412a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public @interface DefaultBehavior { 1413a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Class<? extends Behavior> value(); 1414a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1415a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1416a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1417a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Interaction behavior plugin for child views of {@link CoordinatorLayout}. 1418a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1419a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>A Behavior implements one or more interactions that a user can take on a child view. 1420a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * These interactions may include drags, swipes, flings, or any other gestures.</p> 1421a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1422a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param <V> The View type that this Behavior operates on 1423a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1424a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public static abstract class Behavior<V extends View> { 1425a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1426a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1427a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Default constructor for instantiating Behaviors. 1428a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1429a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public Behavior() { 1430a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1431a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1432a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1433a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Default constructor for inflating Behaviors from layout. The Behavior will have 1434a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * the opportunity to parse specially defined layout parameters. These parameters will 1435a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * appear on the child view tag. 1436a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1437a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param context 1438a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param attrs 1439a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1440a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public Behavior(Context context, AttributeSet attrs) { 1441a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1442a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1443a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1444a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Respond to CoordinatorLayout touch events before they are dispatched to child views. 1445a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1446a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>Behaviors can use this to monitor inbound touch events until one decides to 1447a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * intercept the rest of the event stream to take an action on its associated child view. 1448a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * This method will return false until it detects the proper intercept conditions, then 1449a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * return true once those conditions have occurred.</p> 1450a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1451a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>Once a Behavior intercepts touch events, the rest of the event stream will 1452a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * be sent to the {@link #onTouchEvent} method.</p> 1453a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1454a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>The default implementation of this method always returns false.</p> 1455a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1456a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent view currently receiving this touch event 1457a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child view associated with this Behavior 1458a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param ev the MotionEvent describing the touch event being processed 1459a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true if this Behavior would like to intercept and take over the event stream. 1460a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * The default always returns false. 1461a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1462a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean onInterceptTouchEvent(CoordinatorLayout parent, V child, MotionEvent ev) { 1463a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return false; 1464a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1465a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1466a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1467a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Respond to CoordinatorLayout touch events after this Behavior has started 1468a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link #onInterceptTouchEvent intercepting} them. 1469a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1470a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>Behaviors may intercept touch events in order to help the CoordinatorLayout 1471a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * manipulate its child views. For example, a Behavior may allow a user to drag a 1472a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * UI pane open or closed. This method should perform actual mutations of view 1473a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * layout state.</p> 1474a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1475a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent view currently receiving this touch event 1476a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child view associated with this Behavior 1477a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param ev the MotionEvent describing the touch event being processed 1478a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true if this Behavior handled this touch event and would like to continue 1479a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * receiving events in this stream. The default always returns false. 1480a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1481a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean onTouchEvent(CoordinatorLayout parent, V child, MotionEvent ev) { 1482a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return false; 1483a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1484a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1485a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1486a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Supply a scrim color that will be painted behind the associated child view. 1487a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1488a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>A scrim may be used to indicate that the other elements beneath it are not currently 1489a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * interactive or actionable, drawing user focus and attention to the views above the scrim. 1490a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * </p> 1491a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1492a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>The default implementation returns {@link Color#BLACK}.</p> 1493a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1494a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent view of the given child 1495a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child view above the scrim 1496a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return the desired scrim color in 0xAARRGGBB format. The default return value is 1497a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link Color#BLACK}. 1498a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @see #getScrimOpacity(CoordinatorLayout, android.view.View) 1499a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1500a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public final int getScrimColor(CoordinatorLayout parent, V child) { 1501a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return Color.BLACK; 1502a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1503a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1504a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1505a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Determine the current opacity of the scrim behind a given child view 1506a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1507a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>A scrim may be used to indicate that the other elements beneath it are not currently 1508a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * interactive or actionable, drawing user focus and attention to the views above the scrim. 1509a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * </p> 1510a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1511a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>The default implementation returns 0.0f.</p> 1512a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1513a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent view of the given child 1514a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child view above the scrim 1515a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return the desired scrim opacity from 0.0f to 1.0f. The default return value is 0.0f. 1516a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1517a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public final float getScrimOpacity(CoordinatorLayout parent, V child) { 1518a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return 0.f; 1519a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1520a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1521a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1522a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Determine whether interaction with views behind the given child in the child order 1523a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * should be blocked. 1524a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1525a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>The default implementation returns true if 1526a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link #getScrimOpacity(CoordinatorLayout, android.view.View)} would return > 0.0f.</p> 1527a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1528a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent view of the given child 1529a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child view to test 1530a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true if {@link #getScrimOpacity(CoordinatorLayout, android.view.View)} would 1531a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * return > 0.0f. 1532a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1533a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean blocksInteractionBelow(CoordinatorLayout parent, V child) { 1534a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return getScrimOpacity(parent, child) > 0.f; 1535a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1536a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1537a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1538a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Determine whether the supplied child view has another specific sibling view as a 1539a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * layout dependency. 1540a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1541a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>This method will be called at least once in response to a layout request. If it 1542a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * returns true for a given child and dependency view pair, the parent CoordinatorLayout 1543a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * will:</p> 1544a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <ol> 1545a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <li>Always lay out this child after the dependent child is laid out, regardless 1546a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * of child order.</li> 1547a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <li>Call {@link #onDependentViewChanged} when the dependency view's layout or 1548a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * position changes.</li> 1549a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * </ol> 1550a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1551a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent view of the given child 1552a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child view to test 1553a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param dependency the proposed dependency of child 1554a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true if child's layout depends on the proposed dependency's layout, 1555a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * false otherwise 1556a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1557a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @see #onDependentViewChanged(CoordinatorLayout, android.view.View, android.view.View) 1558a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1559a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean layoutDependsOn(CoordinatorLayout parent, V child, View dependency) { 1560a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return false; 1561a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1562a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1563a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1564a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * Respond to a change in a child's dependent view 1565a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * 1566a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * <p>This method is called whenever a dependent view changes in size or position outside 1567a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * of the standard layout flow. A Behavior may use this method to appropriately update 1568a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * the child view in response.</p> 1569a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1570a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * <p>A view's dependency is determined by 1571a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * {@link #layoutDependsOn(CoordinatorLayout, android.view.View, android.view.View)} or 1572a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * if {@code child} has set another view as it's anchor.</p> 1573a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1574a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>Note that if a Behavior changes the layout of a child via this method, it should 1575a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * also be able to reconstruct the correct position in 1576a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link #onLayoutChild(CoordinatorLayout, android.view.View, int) onLayoutChild}. 1577a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <code>onDependentViewChanged</code> will not be called during normal layout since 1578a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * the layout of each child view will always happen in dependency order.</p> 1579a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1580a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>If the Behavior changes the child view's size or position, it should return true. 1581a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * The default implementation returns false.</p> 1582a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1583a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent view of the given child 1584a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child view to manipulate 1585a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param dependency the dependent view that changed 1586a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true if the Behavior changed the child view's size or position, false otherwise 1587a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1588a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean onDependentViewChanged(CoordinatorLayout parent, V child, View dependency) { 1589a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return false; 1590a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1591a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1592a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1593a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Determine whether the given child view should be considered dirty. 1594a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1595a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>If a property determined by the Behavior such as other dependent views would change, 1596a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * the Behavior should report a child view as dirty. This will prompt the CoordinatorLayout 1597a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * to re-query Behavior-determined properties as appropriate.</p> 1598a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1599a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent view of the given child 1600a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child view to check 1601a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true if child is dirty 1602a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1603a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean isDirty(CoordinatorLayout parent, V child) { 1604a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return false; 1605a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1606a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1607a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1608a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Called when the parent CoordinatorLayout is about to measure the given child view. 1609a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1610a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>This method can be used to perform custom or modified measurement of a child view 1611a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * in place of the default child measurement behavior. The Behavior's implementation 1612a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * can delegate to the standard CoordinatorLayout measurement behavior by calling 1613a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link CoordinatorLayout#onMeasureChild(android.view.View, int, int, int, int) 1614a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * parent.onMeasureChild}.</p> 1615a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1616a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent CoordinatorLayout 1617a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child to measure 1618a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parentWidthMeasureSpec the width requirements for this view 1619a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param widthUsed extra space that has been used up by the parent 1620a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * horizontally (possibly by other children of the parent) 1621a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parentHeightMeasureSpec the height requirements for this view 1622a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param heightUsed extra space that has been used up by the parent 1623a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * vertically (possibly by other children of the parent) 1624a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true if the Behavior measured the child view, false if the CoordinatorLayout 1625a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * should perform its default measurement 1626a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1627a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean onMeasureChild(CoordinatorLayout parent, V child, 1628a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int parentWidthMeasureSpec, int widthUsed, 1629a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int parentHeightMeasureSpec, int heightUsed) { 1630a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return false; 1631a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1632a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1633a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1634a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Called when the parent CoordinatorLayout is about the lay out the given child view. 1635a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1636a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>This method can be used to perform custom or modified layout of a child view 1637a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * in place of the default child layout behavior. The Behavior's implementation can 1638a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * delegate to the standard CoordinatorLayout measurement behavior by calling 1639a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link CoordinatorLayout#onLayoutChild(android.view.View, int) 1640a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * parent.onMeasureChild}.</p> 1641a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1642a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>If a Behavior implements 1643a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link #onDependentViewChanged(CoordinatorLayout, android.view.View, android.view.View)} 1644a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * to change the position of a view in response to a dependent view changing, it 1645a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * should also implement <code>onLayoutChild</code> in such a way that respects those 1646a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * dependent views. <code>onLayoutChild</code> will always be called for a dependent view 1647a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <em>after</em> its dependency has been laid out.</p> 1648a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1649a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent CoordinatorLayout 1650a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child view to lay out 1651a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param layoutDirection the resolved layout direction for the CoordinatorLayout, such as 1652a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link ViewCompat#LAYOUT_DIRECTION_LTR} or 1653a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link ViewCompat#LAYOUT_DIRECTION_RTL}. 1654a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true if the Behavior performed layout of the child view, false to request 1655a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * default layout behavior 1656a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1657a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean onLayoutChild(CoordinatorLayout parent, V child, int layoutDirection) { 1658a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return false; 1659a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1660a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1661a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Utility methods for accessing child-specific, behavior-modifiable properties. 1662a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1663a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1664a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Associate a Behavior-specific tag object with the given child view. 1665a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * This object will be stored with the child view's LayoutParams. 1666a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1667a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child view to set tag with 1668a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param tag tag object to set 1669a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1670a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public static void setTag(View child, Object tag) { 1671a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 1672a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell lp.mBehaviorTag = tag; 1673a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1674a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1675a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1676a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Get the behavior-specific tag object with the given child view. 1677a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * This object is stored with the child view's LayoutParams. 1678a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1679a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child view to get tag with 1680a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return the previously stored tag object 1681a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1682a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public static Object getTag(View child) { 1683a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 1684a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return lp.mBehaviorTag; 1685a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 16865cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 16875cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 16885cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell /** 16895cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * Called when a descendant of the CoordinatorLayout attempts to initiate a nested scroll. 16905cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 16915cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p>Any Behavior associated with any direct child of the CoordinatorLayout may respond 16925cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * to this event and return true to indicate that the CoordinatorLayout should act as 16935cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * a nested scrolling parent for this scroll. Only Behaviors that return true from 16945cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * this method will receive subsequent nested scroll events.</p> 16955cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 16965cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is 16975cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * associated with 16985cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param child the child view of the CoordinatorLayout this Behavior is associated with 16995cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param directTargetChild the child view of the CoordinatorLayout that either is or 17005cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * contains the target of the nested scroll operation 17015cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param target the descendant view of the CoordinatorLayout initiating the nested scroll 17025cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param nestedScrollAxes the axes that this nested scroll applies to. See 17035cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * {@link ViewCompat#SCROLL_AXIS_HORIZONTAL}, 17045cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * {@link ViewCompat#SCROLL_AXIS_VERTICAL} 17055cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @return true if the Behavior wishes to accept this nested scroll 17065cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 17075cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @see NestedScrollingParent#onStartNestedScroll(View, View, int) 17085cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell */ 17095cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, 17105cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell V child, View directTargetChild, View target, int nestedScrollAxes) { 17115cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell return false; 17125cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 17135cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 17145cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell /** 17155cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * Called when a nested scroll has been accepted by the CoordinatorLayout. 17165cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 17175cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p>Any Behavior associated with any direct child of the CoordinatorLayout may elect 17185cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * to accept the nested scroll as part of {@link #onStartNestedScroll}. Each Behavior 17195cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * that returned true will receive subsequent nested scroll events for that nested scroll. 17205cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * </p> 17215cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 17225cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is 17235cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * associated with 17245cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param child the child view of the CoordinatorLayout this Behavior is associated with 17255cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param directTargetChild the child view of the CoordinatorLayout that either is or 17265cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * contains the target of the nested scroll operation 17275cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param target the descendant view of the CoordinatorLayout initiating the nested scroll 17285cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param nestedScrollAxes the axes that this nested scroll applies to. See 17295cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * {@link ViewCompat#SCROLL_AXIS_HORIZONTAL}, 17305cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * {@link ViewCompat#SCROLL_AXIS_VERTICAL} 17315cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 17325cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @see NestedScrollingParent#onNestedScrollAccepted(View, View, int) 17335cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell */ 17345cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell public void onNestedScrollAccepted(CoordinatorLayout coordinatorLayout, V child, 17355cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell View directTargetChild, View target, int nestedScrollAxes) { 17365cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell // Do nothing 17375cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 17385cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 17395cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell /** 17405cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * Called when a nested scroll has ended. 17415cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 17425cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p>Any Behavior associated with any direct child of the CoordinatorLayout may elect 17435cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * to accept the nested scroll as part of {@link #onStartNestedScroll}. Each Behavior 17445cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * that returned true will receive subsequent nested scroll events for that nested scroll. 17455cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * </p> 17465cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 17475cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p><code>onStopNestedScroll</code> marks the end of a single nested scroll event 17485cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * sequence. This is a good place to clean up any state related to the nested scroll. 17495cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * </p> 17505cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 17515cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is 17525cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * associated with 17535cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param child the child view of the CoordinatorLayout this Behavior is associated with 17545cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param target the descendant view of the CoordinatorLayout that initiated 17555cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * the nested scroll 17565cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 17575cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @see NestedScrollingParent#onStopNestedScroll(View) 17585cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell */ 17595cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, V child, View target) { 17605cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell // Do nothing 17615cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 17625cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 17635cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell /** 17645cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * Called when a nested scroll in progress has updated and the target has scrolled or 17655cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * attempted to scroll. 17665cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 17675cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p>Any Behavior associated with the direct child of the CoordinatorLayout may elect 17685cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * to accept the nested scroll as part of {@link #onStartNestedScroll}. Each Behavior 17695cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * that returned true will receive subsequent nested scroll events for that nested scroll. 17705cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * </p> 17715cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 17725cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p><code>onNestedScroll</code> is called each time the nested scroll is updated by the 17735cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * nested scrolling child, with both consumed and unconsumed components of the scroll 17745cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * supplied in pixels. <em>Each Behavior responding to the nested scroll will receive the 17755cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * same values.</em> 17765cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * </p> 17775cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 17785cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is 17795cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * associated with 17805cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param child the child view of the CoordinatorLayout this Behavior is associated with 17815cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param target the descendant view of the CoordinatorLayout performing the nested scroll 17825cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param dxConsumed horizontal pixels consumed by the target's own scrolling operation 17835cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param dyConsumed vertical pixels consumed by the target's own scrolling operation 17845cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param dxUnconsumed horizontal pixels not consumed by the target's own scrolling 17855cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * operation, but requested by the user 17865cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param dyUnconsumed vertical pixels not consumed by the target's own scrolling operation, 17875cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * but requested by the user 17885cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 17895cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @see NestedScrollingParent#onNestedScroll(View, int, int, int, int) 17905cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell */ 17915cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell public void onNestedScroll(CoordinatorLayout coordinatorLayout, V child, View target, 17925cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) { 17935cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell // Do nothing 17945cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 17955cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 17965cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell /** 17975cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * Called when a nested scroll in progress is about to update, before the target has 17985cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * consumed any of the scrolled distance. 17995cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 18005cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p>Any Behavior associated with the direct child of the CoordinatorLayout may elect 18015cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * to accept the nested scroll as part of {@link #onStartNestedScroll}. Each Behavior 18025cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * that returned true will receive subsequent nested scroll events for that nested scroll. 18035cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * </p> 18045cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 18055cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p><code>onNestedPreScroll</code> is called each time the nested scroll is updated 18065cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * by the nested scrolling child, before the nested scrolling child has consumed the scroll 18075cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * distance itself. <em>Each Behavior responding to the nested scroll will receive the 18085cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * same values.</em> The CoordinatorLayout will report as consumed the maximum number 18095cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * of pixels in either direction that any Behavior responding to the nested scroll reported 18105cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * as consumed.</p> 18115cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 18125cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is 18135cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * associated with 18145cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param child the child view of the CoordinatorLayout this Behavior is associated with 18155cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param target the descendant view of the CoordinatorLayout performing the nested scroll 18165cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param dx the raw horizontal number of pixels that the user attempted to scroll 18175cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param dy the raw vertical number of pixels that the user attempted to scroll 18185cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param consumed out parameter. consumed[0] should be set to the distance of dx that 18195cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * was consumed, consumed[1] should be set to the distance of dy that 18205cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * was consumed 18215cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 18225cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @see NestedScrollingParent#onNestedPreScroll(View, int, int, int[]) 18235cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell */ 18245cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, V child, View target, 18255cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell int dx, int dy, int[] consumed) { 18265cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell // Do nothing 18275cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 18285cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 18295cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell /** 18305cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * Called when a nested scrolling child is starting a fling or an action that would 18315cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * be a fling. 18325cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 18335cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p>Any Behavior associated with the direct child of the CoordinatorLayout may elect 18345cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * to accept the nested scroll as part of {@link #onStartNestedScroll}. Each Behavior 18355cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * that returned true will receive subsequent nested scroll events for that nested scroll. 18365cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * </p> 18375cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 18385cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p><code>onNestedFling</code> is called when the current nested scrolling child view 18395cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * detects the proper conditions for a fling. It reports if the child itself consumed 18405cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * the fling. If it did not, the child is expected to show some sort of overscroll 18415cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * indication. This method should return true if it consumes the fling, so that a child 18425cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * that did not itself take an action in response can choose not to show an overfling 18435cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * indication.</p> 18445cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 18455cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is 18465cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * associated with 18475cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param child the child view of the CoordinatorLayout this Behavior is associated with 18485cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param target the descendant view of the CoordinatorLayout performing the nested scroll 18495cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param velocityX horizontal velocity of the attempted fling 18505cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param velocityY vertical velocity of the attempted fling 18515cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param consumed true if the nested child view consumed the fling 18525cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @return true if the Behavior consumed the fling 18535cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 18545cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @see NestedScrollingParent#onNestedFling(View, float, float, boolean) 18555cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell */ 18565cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell public boolean onNestedFling(CoordinatorLayout coordinatorLayout, V child, View target, 18575cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell float velocityX, float velocityY, boolean consumed) { 18585cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell return false; 18595cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 18605cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 18615cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell /** 18625cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * Called when a nested scrolling child is about to start a fling. 18635cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 18645cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p>Any Behavior associated with the direct child of the CoordinatorLayout may elect 18655cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * to accept the nested scroll as part of {@link #onStartNestedScroll}. Each Behavior 18665cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * that returned true will receive subsequent nested scroll events for that nested scroll. 18675cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * </p> 18685cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 18695cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p><code>onNestedPreFling</code> is called when the current nested scrolling child view 18705cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * detects the proper conditions for a fling, but it has not acted on it yet. A 18715cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * Behavior can return true to indicate that it consumed the fling. If at least one 18725cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * Behavior returns true, the fling should not be acted upon by the child.</p> 18735cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 18745cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is 18755cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * associated with 18765cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param child the child view of the CoordinatorLayout this Behavior is associated with 18775cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param target the descendant view of the CoordinatorLayout performing the nested scroll 18785cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param velocityX horizontal velocity of the attempted fling 18795cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param velocityY vertical velocity of the attempted fling 18805cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @return true if the Behavior consumed the fling 18815cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 18825cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @see NestedScrollingParent#onNestedPreFling(View, float, float) 18835cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell */ 18845cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell public boolean onNestedPreFling(CoordinatorLayout coordinatorLayout, V child, View target, 18855cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell float velocityX, float velocityY) { 18865cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell return false; 18875cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 1888a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1889a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1890a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1891a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Parameters describing the desired layout for a child of a {@link CoordinatorLayout}. 1892a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1893a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public static class LayoutParams extends ViewGroup.MarginLayoutParams { 1894a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1895a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * A {@link Behavior} that the child view should obey. 1896a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1897a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Behavior mBehavior; 1898a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1899a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean mBehaviorResolved = false; 1900a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1901a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1902a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * A {@link Gravity} value describing how this child view should lay out. 1903a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * If an {@link #setAnchorId(int) anchor} is also specified, the gravity describes 1904a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * how this child view should be positioned relative to its anchored position. 1905a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1906a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public int gravity = Gravity.NO_GRAVITY; 1907a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1908a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1909a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * A {@link Gravity} value describing which edge of a child view's 1910a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link #getAnchorId() anchor} view the child should position itself relative to. 1911a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1912a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public int anchorGravity = Gravity.NO_GRAVITY; 1913a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1914a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1915a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * The index of the horizontal keyline specified to the parent CoordinatorLayout that this 1916a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * child should align relative to. If an {@link #setAnchorId(int) anchor} is present the 1917a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * keyline will be ignored. 1918a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1919a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public int keyline = -1; 1920a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1921a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1922a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * A {@link View#getId() view id} of a descendant view of the CoordinatorLayout that 1923a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * this child should position relative to. 1924a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1925a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int mAnchorId = View.NO_ID; 1926a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1927a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell View mAnchorView; 1928a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell View mAnchorDirectChild; 1929a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 19305cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell private boolean mDidBlockInteraction; 19315cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell private boolean mDidAcceptNestedScroll; 1932a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes private boolean mDidChangeAfterNestedScroll; 1933a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1934a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Rect mLastChildRect = new Rect(); 1935a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1936a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Object mBehaviorTag; 1937a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1938a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public LayoutParams(int width, int height) { 1939a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell super(width, height); 1940a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1941a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1942a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell LayoutParams(Context context, AttributeSet attrs) { 1943a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell super(context, attrs); 1944a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1945a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final TypedArray a = context.obtainStyledAttributes(attrs, 1946a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell R.styleable.CoordinatorLayout_LayoutParams); 1947a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1948a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell this.gravity = a.getInteger( 1949a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell R.styleable.CoordinatorLayout_LayoutParams_android_layout_gravity, 1950a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Gravity.NO_GRAVITY); 1951a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mAnchorId = a.getResourceId(R.styleable.CoordinatorLayout_LayoutParams_layout_anchor, 1952a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell View.NO_ID); 1953a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell this.anchorGravity = a.getInteger( 1954a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell R.styleable.CoordinatorLayout_LayoutParams_layout_anchorGravity, 1955a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Gravity.NO_GRAVITY); 1956a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1957a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell this.keyline = a.getInteger(R.styleable.CoordinatorLayout_LayoutParams_layout_keyline, 1958a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell -1); 1959a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1960a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mBehaviorResolved = a.hasValue( 1961a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell R.styleable.CoordinatorLayout_LayoutParams_layout_behavior); 1962a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mBehaviorResolved) { 1963a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mBehavior = parseBehavior(context, attrs, a.getString( 1964a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell R.styleable.CoordinatorLayout_LayoutParams_layout_behavior)); 1965a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1966a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1967a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell a.recycle(); 1968a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1969a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1970a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public LayoutParams(LayoutParams p) { 1971a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell super(p); 1972a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1973a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1974a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public LayoutParams(MarginLayoutParams p) { 1975a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell super(p); 1976a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1977a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1978a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public LayoutParams(ViewGroup.LayoutParams p) { 1979a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell super(p); 1980a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1981a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1982a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1983a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Get the id of this view's anchor. 1984a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1985a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>The view with this id must be a descendant of the CoordinatorLayout containing 1986a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * the child view this LayoutParams belongs to. It may not be the child view with 1987a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * this LayoutParams or a descendant of it.</p> 1988a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1989a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return A {@link View#getId() view id} or {@link View#NO_ID} if there is no anchor 1990a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1991a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public int getAnchorId() { 1992a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return mAnchorId; 1993a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1994a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1995a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1996a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Get the id of this view's anchor. 1997a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1998a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>The view with this id must be a descendant of the CoordinatorLayout containing 1999a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * the child view this LayoutParams belongs to. It may not be the child view with 2000a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * this LayoutParams or a descendant of it.</p> 2001a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2002a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param id The {@link View#getId() view id} of the anchor or 2003a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link View#NO_ID} if there is no anchor 2004a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2005a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public void setAnchorId(int id) { 2006a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell invalidateAnchor(); 2007a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mAnchorId = id; 2008a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2009a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2010a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2011a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Get the behavior governing the layout and interaction of the child view within 2012a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * a parent CoordinatorLayout. 2013a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2014a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return The current behavior or null if no behavior is specified 2015a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2016a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public Behavior getBehavior() { 2017a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return mBehavior; 2018a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2019a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2020a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2021a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Set the behavior governing the layout and interaction of the child view within 2022a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * a parent CoordinatorLayout. 2023a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2024a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>Setting a new behavior will remove any currently associated 2025a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link Behavior#setTag(android.view.View, Object) Behavior tag}.</p> 2026a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2027a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param behavior The behavior to set or null for no special behavior 2028a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2029a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public void setBehavior(Behavior behavior) { 2030a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mBehavior != behavior) { 2031a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mBehavior = behavior; 2032a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mBehaviorTag = null; 2033a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mBehaviorResolved = true; 2034a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2035a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2036a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2037a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2038a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Set the last known position rect for this child view 2039a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param r the rect to set 2040a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2041a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void setLastChildRect(Rect r) { 2042a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mLastChildRect.set(r); 2043a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2044a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2045a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2046a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Get the last known position rect for this child view. 2047a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Note: do not mutate the result of this call. 2048a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2049a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Rect getLastChildRect() { 2050a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return mLastChildRect; 2051a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2052a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2053a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2054a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Returns true if the anchor id changed to another valid view id since the anchor view 2055a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * was resolved. 2056a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2057a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean checkAnchorChanged() { 2058a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return mAnchorView == null && mAnchorId != View.NO_ID; 2059a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2060a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2061a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2062a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Returns true if the associated Behavior previously blocked interaction with other views 2063a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * below the associated child since the touch behavior tracking was last 2064a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link #resetTouchBehaviorTracking() reset}. 2065a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2066a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @see #isBlockingInteractionBelow(CoordinatorLayout, android.view.View) 2067a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2068a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean didBlockInteraction() { 2069a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mBehavior == null) { 2070a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mDidBlockInteraction = false; 2071a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2072a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return mDidBlockInteraction; 2073a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2074a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2075a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2076a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Check if the associated Behavior wants to block interaction below the given child 2077a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * view. The given child view should be the child this LayoutParams is associated with. 2078a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2079a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>Once interaction is blocked, it will remain blocked until touch interaction tracking 2080a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * is {@link #resetTouchBehaviorTracking() reset}.</p> 2081a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2082a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent CoordinatorLayout 2083a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child view this LayoutParams is associated with 2084a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true to block interaction below the given child 2085a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2086a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean isBlockingInteractionBelow(CoordinatorLayout parent, View child) { 2087a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mDidBlockInteraction) { 2088a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return true; 2089a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2090a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2091a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return mDidBlockInteraction |= mBehavior != null 2092a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell ? mBehavior.blocksInteractionBelow(parent, child) 2093a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell : false; 2094a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2095a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2096a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2097a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Reset tracking of Behavior-specific touch interactions. This includes 2098a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * interaction blocking. 2099a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2100a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @see #isBlockingInteractionBelow(CoordinatorLayout, android.view.View) 2101a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @see #didBlockInteraction() 2102a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2103a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void resetTouchBehaviorTracking() { 2104a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mDidBlockInteraction = false; 2105a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2106a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 21075cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell void resetNestedScroll() { 21085cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell mDidAcceptNestedScroll = false; 21095cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 21105cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 21115cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell void acceptNestedScroll(boolean accept) { 21125cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell mDidAcceptNestedScroll = accept; 21135cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 21145cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 21155cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell boolean isNestedScrollAccepted() { 21165cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell return mDidAcceptNestedScroll; 21175cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 21185cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 2119a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes boolean getChangedAfterNestedScroll() { 2120a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes return mDidChangeAfterNestedScroll; 2121a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 2122a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 2123a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes void setChangedAfterNestedScroll(boolean changed) { 2124a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes mDidChangeAfterNestedScroll = changed; 2125a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 2126a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 2127a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes void resetChangedAfterNestedScroll() { 2128a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes mDidChangeAfterNestedScroll = false; 2129a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 2130a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 2131a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2132a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Check if an associated child view depends on another child view of the CoordinatorLayout. 2133a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2134a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent CoordinatorLayout 2135a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child to check 2136a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param dependency the proposed dependency to check 2137a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true if child depends on dependency 2138a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2139a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean dependsOn(CoordinatorLayout parent, View child, View dependency) { 2140a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return dependency == mAnchorDirectChild 2141a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell || (mBehavior != null && mBehavior.layoutDependsOn(parent, child, dependency)); 2142a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2143a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2144a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2145a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Invalidate the cached anchor view and direct child ancestor of that anchor. 2146a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * The anchor will need to be 2147a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link #findAnchorView(CoordinatorLayout, android.view.View) found} before 2148a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * being used again. 2149a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2150a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void invalidateAnchor() { 2151a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mAnchorView = mAnchorDirectChild = null; 2152a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2153a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2154a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2155a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Locate the appropriate anchor view by the current {@link #setAnchorId(int) anchor id} 2156a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * or return the cached anchor view if already known. 2157a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2158a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent CoordinatorLayout 2159a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param forChild the child this LayoutParams is associated with 2160a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return the located descendant anchor view, or null if the anchor id is 2161a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link View#NO_ID}. 2162a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2163a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell View findAnchorView(CoordinatorLayout parent, View forChild) { 2164a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mAnchorId == View.NO_ID) { 2165a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mAnchorView = mAnchorDirectChild = null; 2166a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return null; 2167a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2168a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2169a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mAnchorView == null || !verifyAnchorView(forChild, parent)) { 2170a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell resolveAnchorView(forChild, parent); 2171a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2172a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return mAnchorView; 2173a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2174a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2175a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2176a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Check if the child associated with this LayoutParams is currently considered 2177a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * "dirty" and needs to be updated. A Behavior should consider a child dirty 2178a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * whenever a property returned by another Behavior method would have changed, 2179a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * such as dependencies. 2180a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2181a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent CoordinatorLayout 2182a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child view associated with this LayoutParams 2183a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true if this child view should be considered dirty 2184a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2185a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean isDirty(CoordinatorLayout parent, View child) { 2186a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return mBehavior != null && mBehavior.isDirty(parent, child); 2187a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2188a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2189a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2190a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Determine the anchor view for the child view this LayoutParams is assigned to. 2191a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Assumes mAnchorId is valid. 2192a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2193a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private void resolveAnchorView(View forChild, CoordinatorLayout parent) { 2194a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mAnchorView = parent.findViewById(mAnchorId); 2195a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mAnchorView != null) { 2196a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell View directChild = mAnchorView; 2197a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (ViewParent p = mAnchorView.getParent(); 2198a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell p != parent && p != null; 2199a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell p = p.getParent()) { 2200a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (p == forChild) { 2201a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (parent.isInEditMode()) { 2202a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mAnchorView = mAnchorDirectChild = null; 2203a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return; 2204a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2205a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell throw new IllegalStateException( 2206a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell "Anchor must not be a descendant of the anchored view"); 2207a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2208a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (p instanceof View) { 2209a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell directChild = (View) p; 2210a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2211a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2212a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mAnchorDirectChild = directChild; 2213a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else { 2214a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (parent.isInEditMode()) { 2215a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mAnchorView = mAnchorDirectChild = null; 2216a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return; 2217a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2218a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell throw new IllegalStateException("Could not find CoordinatorLayout descendant view" 2219a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell + " with id " + parent.getResources().getResourceName(mAnchorId) 2220a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell + " to anchor view " + forChild); 2221a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2222a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2223a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2224a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2225a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Verify that the previously resolved anchor view is still valid - that it is still 2226a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * a descendant of the expected parent view, it is not the child this LayoutParams 2227a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * is assigned to or a descendant of it, and it has the expected id. 2228a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2229a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private boolean verifyAnchorView(View forChild, CoordinatorLayout parent) { 2230a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mAnchorView.getId() != mAnchorId) { 2231a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return false; 2232a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2233a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2234a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell View directChild = mAnchorView; 2235a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (ViewParent p = mAnchorView.getParent(); 2236a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell p != parent; 2237a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell p = p.getParent()) { 2238a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (p == null || p == forChild) { 2239a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mAnchorView = mAnchorDirectChild = null; 2240a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return false; 2241a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2242a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (p instanceof View) { 2243a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell directChild = (View) p; 2244a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2245a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2246a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mAnchorDirectChild = directChild; 2247a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return true; 2248a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2249a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2250a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell} 2251