1a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell/* 2a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Copyright (C) 2015 The Android Open Source Project 3a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 4a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Licensed under the Apache License, Version 2.0 (the "License"); 5a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * you may not use this file except in compliance with the License. 6a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * You may obtain a copy of the License at 7a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 8a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * http://www.apache.org/licenses/LICENSE-2.0 9a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 10a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Unless required by applicable law or agreed to in writing, software 11a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * distributed under the License is distributed on an "AS IS" BASIS, 12a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * See the License for the specific language governing permissions and 14a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * limitations under the License. 15a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 16a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 17a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellpackage android.support.design.widget; 18a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 19a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.content.Context; 20a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.content.res.Resources; 21a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.content.res.TypedArray; 22a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.graphics.Canvas; 23a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.graphics.Color; 24a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.graphics.Paint; 25a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.graphics.Rect; 2675284fffafacd32f4d178020050589f9e70e5ed9Chris Banesimport android.graphics.drawable.ColorDrawable; 2775284fffafacd32f4d178020050589f9e70e5ed9Chris Banesimport android.graphics.drawable.Drawable; 28a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.os.Build; 29e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banesimport android.os.Parcel; 30e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banesimport android.os.Parcelable; 31a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.os.SystemClock; 32a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.support.design.R; 3375284fffafacd32f4d178020050589f9e70e5ed9Chris Banesimport android.support.v4.content.ContextCompat; 34a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.support.v4.view.GravityCompat; 3588cccf6c76b6a1c2d67152c2de5599f3c8301b18Chris Banesimport android.support.v4.view.MotionEventCompat; 36a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.support.v4.view.NestedScrollingParent; 37a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.support.v4.view.NestedScrollingParentHelper; 38a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.support.v4.view.ViewCompat; 3975284fffafacd32f4d178020050589f9e70e5ed9Chris Banesimport android.support.v4.view.WindowInsetsCompat; 40a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.text.TextUtils; 41a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.util.AttributeSet; 42a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.util.Log; 43e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banesimport android.util.SparseArray; 44a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.view.Gravity; 45a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.view.MotionEvent; 46a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.view.View; 47a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.view.ViewGroup; 48a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.view.ViewParent; 49a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.view.ViewTreeObserver; 50a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 51a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport java.lang.annotation.Retention; 52a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport java.lang.annotation.RetentionPolicy; 53a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport java.lang.reflect.Constructor; 54a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport java.util.ArrayList; 55a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport java.util.Collections; 56a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport java.util.Comparator; 57a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport java.util.HashMap; 58a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport java.util.List; 59a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport java.util.Map; 60a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 61a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell/** 62a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * CoordinatorLayout is a super-powered {@link android.widget.FrameLayout FrameLayout}. 63a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 64a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>CoordinatorLayout is intended for two primary use cases:</p> 65a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <ol> 66a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <li>As a top-level application decor or chrome layout</li> 67a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <li>As a container for a specific interaction with one or more child views</li> 68a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * </ol> 69a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 70a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>By specifying {@link CoordinatorLayout.Behavior Behaviors} for child views of a 71a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * CoordinatorLayout you can provide many different interactions within a single parent and those 72a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * views can also interact with one another. View classes can specify a default behavior when 73a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * used as a child of a CoordinatorLayout using the 74a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link CoordinatorLayout.DefaultBehavior DefaultBehavior} annotation.</p> 75a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 76a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>Behaviors may be used to implement a variety of interactions and additional layout 77a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * modifications ranging from sliding drawers and panels to swipe-dismissable elements and buttons 78a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * that stick to other elements as they move and animate.</p> 79a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 80a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>Children of a CoordinatorLayout may have an 81a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link CoordinatorLayout.LayoutParams#setAnchorId(int) anchor}. This view id must correspond 82a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * to an arbitrary descendant of the CoordinatorLayout, but it may not be the anchored child itself 83a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * or a descendant of the anchored child. This can be used to place floating views relative to 84a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * other arbitrary content panes.</p> 85a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 86a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellpublic class CoordinatorLayout extends ViewGroup implements NestedScrollingParent { 87a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell static final String TAG = "CoordinatorLayout"; 88a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell static final String WIDGET_PACKAGE_NAME = CoordinatorLayout.class.getPackage().getName(); 89a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 90d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes private static final int TYPE_ON_INTERCEPT = 0; 91d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes private static final int TYPE_ON_TOUCH = 1; 92d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes 93a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell static { 94a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes if (Build.VERSION.SDK_INT >= 21) { 95a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell TOP_SORTED_CHILDREN_COMPARATOR = new ViewElevationComparator(); 9675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes INSETS_HELPER = new CoordinatorLayoutInsetsHelperLollipop(); 97a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else { 98a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell TOP_SORTED_CHILDREN_COMPARATOR = null; 9975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes INSETS_HELPER = null; 100a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 101a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 102a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 103a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell static final Class<?>[] CONSTRUCTOR_PARAMS = new Class<?>[] { 104a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Context.class, 105a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell AttributeSet.class 106a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell }; 107a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 108a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell static final ThreadLocal<Map<String, Constructor<Behavior>>> sConstructors = 109a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell new ThreadLocal<>(); 110a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 111a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Comparator<View> mLayoutDependencyComparator = new Comparator<View>() { 112a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 113a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public int compare(View lhs, View rhs) { 114a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (lhs == rhs) { 115a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return 0; 116a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else if (((LayoutParams) lhs.getLayoutParams()).dependsOn( 117a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell CoordinatorLayout.this, lhs, rhs)) { 118a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return 1; 119a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else if (((LayoutParams) rhs.getLayoutParams()).dependsOn( 120a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell CoordinatorLayout.this, rhs, lhs)) { 121a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return -1; 122a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else { 123a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return 0; 124a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 125a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 126a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell }; 127a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 128a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell static final Comparator<View> TOP_SORTED_CHILDREN_COMPARATOR; 12975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes static final CoordinatorLayoutInsetsHelper INSETS_HELPER; 130a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 131a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private final List<View> mDependencySortedChildren = new ArrayList<View>(); 132a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes private final List<View> mTempList1 = new ArrayList<>(); 133a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes private final List<View> mTempDependenciesList = new ArrayList<>(); 134a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private final Rect mTempRect1 = new Rect(); 135a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private final Rect mTempRect2 = new Rect(); 136a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private final Rect mTempRect3 = new Rect(); 1375cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell private final int[] mTempIntPair = new int[2]; 138a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private Paint mScrimPaint; 139a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 140a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private boolean mIsAttachedToWindow; 141a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 142a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private int[] mKeylines; 143a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 144a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private View mBehaviorTouchView; 1455cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell private View mNestedScrollingDirectChild; 1465cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell private View mNestedScrollingTarget; 147a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 148a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private OnPreDrawListener mOnPreDrawListener; 149a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private boolean mNeedsPreDrawListener; 150a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 15175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes private WindowInsetsCompat mLastInsets; 15275284fffafacd32f4d178020050589f9e70e5ed9Chris Banes private boolean mDrawStatusBarBackground; 15375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes private Drawable mStatusBarBackground; 15475284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 1550b00489086b22c9688c8c04990dadf54489d45e3Chris Banes private OnHierarchyChangeListener mOnHierarchyChangeListener; 1560b00489086b22c9688c8c04990dadf54489d45e3Chris Banes 157a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private final NestedScrollingParentHelper mNestedScrollingParentHelper = 158a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell new NestedScrollingParentHelper(this); 159a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 160a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public CoordinatorLayout(Context context) { 161a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell this(context, null); 162a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 163a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 164a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public CoordinatorLayout(Context context, AttributeSet attrs) { 165a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell this(context, attrs, 0); 166a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 167a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 168a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public CoordinatorLayout(Context context, AttributeSet attrs, int defStyleAttr) { 169a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell super(context, attrs, defStyleAttr); 170a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 171a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CoordinatorLayout, 17275284fffafacd32f4d178020050589f9e70e5ed9Chris Banes defStyleAttr, R.style.Widget_Design_CoordinatorLayout); 173a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int keylineArrayRes = a.getResourceId(R.styleable.CoordinatorLayout_keylines, 0); 174a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (keylineArrayRes != 0) { 175a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Resources res = context.getResources(); 176a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mKeylines = res.getIntArray(keylineArrayRes); 177a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final float density = res.getDisplayMetrics().density; 178a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int count = mKeylines.length; 179a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int i = 0; i < count; i++) { 180a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mKeylines[i] *= density; 181a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 182a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 18375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes mStatusBarBackground = a.getDrawable(R.styleable.CoordinatorLayout_statusBarBackground); 184a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell a.recycle(); 18575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 18675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes if (INSETS_HELPER != null) { 18775284fffafacd32f4d178020050589f9e70e5ed9Chris Banes INSETS_HELPER.setupForWindowInsets(this, new ApplyInsetsListener()); 18875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 1890b00489086b22c9688c8c04990dadf54489d45e3Chris Banes super.setOnHierarchyChangeListener(new HierarchyChangeListener()); 1900b00489086b22c9688c8c04990dadf54489d45e3Chris Banes } 1910b00489086b22c9688c8c04990dadf54489d45e3Chris Banes 1920b00489086b22c9688c8c04990dadf54489d45e3Chris Banes @Override 1930b00489086b22c9688c8c04990dadf54489d45e3Chris Banes public void setOnHierarchyChangeListener(OnHierarchyChangeListener onHierarchyChangeListener) { 1940b00489086b22c9688c8c04990dadf54489d45e3Chris Banes mOnHierarchyChangeListener = onHierarchyChangeListener; 195a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 196a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 197a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 198a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public void onAttachedToWindow() { 199a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell super.onAttachedToWindow(); 2005cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell resetTouchBehaviors(); 201a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mNeedsPreDrawListener) { 202a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mOnPreDrawListener == null) { 203a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mOnPreDrawListener = new OnPreDrawListener(); 204a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 205a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final ViewTreeObserver vto = getViewTreeObserver(); 206a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell vto.addOnPreDrawListener(mOnPreDrawListener); 207a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 208e3f6ba486fec4e11ca7508049ac81de4c7102f23Chris Banes if (mLastInsets == null && ViewCompat.getFitsSystemWindows(this)) { 209e3f6ba486fec4e11ca7508049ac81de4c7102f23Chris Banes // We're set to fitSystemWindows but we haven't had any insets yet... 210e3f6ba486fec4e11ca7508049ac81de4c7102f23Chris Banes // We should request a new dispatch of window insets 211e3f6ba486fec4e11ca7508049ac81de4c7102f23Chris Banes ViewCompat.requestApplyInsets(this); 212e3f6ba486fec4e11ca7508049ac81de4c7102f23Chris Banes } 213a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mIsAttachedToWindow = true; 214a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 215a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 216a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 217a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public void onDetachedFromWindow() { 218a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell super.onDetachedFromWindow(); 2195cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell resetTouchBehaviors(); 220a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mNeedsPreDrawListener && mOnPreDrawListener != null) { 221a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final ViewTreeObserver vto = getViewTreeObserver(); 222a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell vto.removeOnPreDrawListener(mOnPreDrawListener); 223a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2245cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (mNestedScrollingTarget != null) { 2255cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell onStopNestedScroll(mNestedScrollingTarget); 2265cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 227a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mIsAttachedToWindow = false; 228a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 229a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 230a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 23175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * Set a drawable to draw in the insets area for the status bar. 23275284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * Note that this will only be activated if this DrawerLayout fitsSystemWindows. 23375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * 23475284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * @param bg Background drawable to draw behind the status bar 23575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes */ 23675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes public void setStatusBarBackground(Drawable bg) { 23775284fffafacd32f4d178020050589f9e70e5ed9Chris Banes mStatusBarBackground = bg; 23875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes invalidate(); 23975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 24075284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 24175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes /** 24275284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * Gets the drawable used to draw in the insets area for the status bar. 24375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * 24475284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * @return The status bar background drawable, or null if none set 24575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes */ 24675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes public Drawable getStatusBarBackground() { 24775284fffafacd32f4d178020050589f9e70e5ed9Chris Banes return mStatusBarBackground; 24875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 24975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 25075284fffafacd32f4d178020050589f9e70e5ed9Chris Banes /** 25175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * Set a drawable to draw in the insets area for the status bar. 25275284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * Note that this will only be activated if this DrawerLayout fitsSystemWindows. 25375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * 25475284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * @param resId Resource id of a background drawable to draw behind the status bar 25575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes */ 25675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes public void setStatusBarBackgroundResource(int resId) { 25775284fffafacd32f4d178020050589f9e70e5ed9Chris Banes setStatusBarBackground(resId != 0 ? ContextCompat.getDrawable(getContext(), resId) : null); 25875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 25975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 26075284fffafacd32f4d178020050589f9e70e5ed9Chris Banes /** 26175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * Set a drawable to draw in the insets area for the status bar. 26275284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * Note that this will only be activated if this DrawerLayout fitsSystemWindows. 26375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * 26475284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * @param color Color to use as a background drawable to draw behind the status bar 26575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * in 0xAARRGGBB format. 26675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes */ 26775284fffafacd32f4d178020050589f9e70e5ed9Chris Banes public void setStatusBarBackgroundColor(int color) { 26875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes setStatusBarBackground(new ColorDrawable(color)); 26975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 27075284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 27175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes private void setWindowInsets(WindowInsetsCompat insets) { 27275284fffafacd32f4d178020050589f9e70e5ed9Chris Banes if (mLastInsets != insets) { 27375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes mLastInsets = insets; 27475284fffafacd32f4d178020050589f9e70e5ed9Chris Banes mDrawStatusBarBackground = insets != null && insets.getSystemWindowInsetTop() > 0; 27575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes setWillNotDraw(!mDrawStatusBarBackground && getBackground() == null); 27675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes dispatchChildApplyWindowInsets(insets); 27775284fffafacd32f4d178020050589f9e70e5ed9Chris Banes requestLayout(); 27875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 27975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 28075284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 28175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes /** 282a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Reset all Behavior-related tracking records either to clean up or in preparation 283a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * for a new event stream. This should be called when attached or detached from a window, 284a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * in response to an UP or CANCEL event, when intercept is request-disallowed 285a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * and similar cases where an event stream in progress will be aborted. 286a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2875cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell private void resetTouchBehaviors() { 288a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mBehaviorTouchView != null) { 289a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Behavior b = ((LayoutParams) mBehaviorTouchView.getLayoutParams()).getBehavior(); 290a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (b != null) { 291a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final long now = SystemClock.uptimeMillis(); 292a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final MotionEvent cancelEvent = MotionEvent.obtain(now, now, 293a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0); 294a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell b.onTouchEvent(this, mBehaviorTouchView, cancelEvent); 295a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell cancelEvent.recycle(); 296a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 297a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mBehaviorTouchView = null; 298a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 299a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 300a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childCount = getChildCount(); 301a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int i = 0; i < childCount; i++) { 302a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final View child = getChildAt(i); 303a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 304a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell lp.resetTouchBehaviorTracking(); 305a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 306a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 307a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 308a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 309a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Populate a list with the current child views, sorted such that the topmost views 310a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * in z-order are at the front of the list. Useful for hit testing and event dispatch. 311a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 312a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private void getTopSortedChildren(List<View> out) { 313a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell out.clear(); 314a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 315a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final boolean useCustomOrder = isChildrenDrawingOrderEnabled(); 316a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childCount = getChildCount(); 317a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int i = childCount - 1; i >= 0; i--) { 318a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childIndex = useCustomOrder ? getChildDrawingOrder(childCount, i) : i; 319a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final View child = getChildAt(childIndex); 320a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell out.add(child); 321a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 322a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 323a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (TOP_SORTED_CHILDREN_COMPARATOR != null) { 324a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Collections.sort(out, TOP_SORTED_CHILDREN_COMPARATOR); 325a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 326a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 327a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 328d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes private boolean performIntercept(MotionEvent ev, final int type) { 329a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean intercepted = false; 330a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean newBlock = false; 331a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 332a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell MotionEvent cancelEvent = null; 333a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 33488cccf6c76b6a1c2d67152c2de5599f3c8301b18Chris Banes final int action = MotionEventCompat.getActionMasked(ev); 335a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 336a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes final List<View> topmostChildList = mTempList1; 337a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getTopSortedChildren(topmostChildList); 338a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 339a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Let topmost child views inspect first 340a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childCount = topmostChildList.size(); 341a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int i = 0; i < childCount; i++) { 342a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final View child = topmostChildList.get(i); 343a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 344a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Behavior b = lp.getBehavior(); 345a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 346a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if ((intercepted || newBlock) && action != MotionEvent.ACTION_DOWN) { 347a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Cancel all behaviors beneath the one that intercepted. 348a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // If the event is "down" then we don't have anything to cancel yet. 349a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (b != null) { 350515613db9b9d82472c8fce69b2b104c277f68b99Chris Banes if (cancelEvent == null) { 351a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final long now = SystemClock.uptimeMillis(); 352a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell cancelEvent = MotionEvent.obtain(now, now, 353a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0); 354a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 355d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes switch (type) { 356d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes case TYPE_ON_INTERCEPT: 357d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes b.onInterceptTouchEvent(this, child, cancelEvent); 358d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes break; 359d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes case TYPE_ON_TOUCH: 360d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes b.onTouchEvent(this, child, cancelEvent); 361d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes break; 362d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes } 363a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 364a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell continue; 365a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 366a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 367d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes if (!intercepted && b != null) { 368d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes switch (type) { 369d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes case TYPE_ON_INTERCEPT: 370d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes intercepted = b.onInterceptTouchEvent(this, child, ev); 371d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes break; 372d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes case TYPE_ON_TOUCH: 373d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes intercepted = b.onTouchEvent(this, child, ev); 374d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes break; 375d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes } 376d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes if (intercepted) { 377d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes mBehaviorTouchView = child; 378d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes } 379a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 380a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 381a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Don't keep going if we're not allowing interaction below this. 382a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Setting newBlock will make sure we cancel the rest of the behaviors. 383a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final boolean wasBlocking = lp.didBlockInteraction(); 384a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final boolean isBlocking = lp.isBlockingInteractionBelow(this, child); 385a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell newBlock = isBlocking && !wasBlocking; 386a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (isBlocking && !newBlock) { 387a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Stop here since we don't have anything more to cancel - we already did 388a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // when the behavior first started blocking things below this point. 389a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 390a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 391a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 392a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 393a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell topmostChildList.clear(); 394a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 395a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return intercepted; 396a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 397a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 398a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 399a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean onInterceptTouchEvent(MotionEvent ev) { 400a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell MotionEvent cancelEvent = null; 401a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 40288cccf6c76b6a1c2d67152c2de5599f3c8301b18Chris Banes final int action = MotionEventCompat.getActionMasked(ev); 403a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 404a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Make sure we reset in case we had missed a previous important event. 405a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (action == MotionEvent.ACTION_DOWN) { 4065cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell resetTouchBehaviors(); 407a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 408a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 409d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes final boolean intercepted = performIntercept(ev, TYPE_ON_INTERCEPT); 410a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 411a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (cancelEvent != null) { 412a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell cancelEvent.recycle(); 413a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 414a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 415a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { 4165cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell resetTouchBehaviors(); 417a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 418a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 419a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return intercepted; 420a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 421a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 422a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 423a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean onTouchEvent(MotionEvent ev) { 424a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean handled = false; 425a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean cancelSuper = false; 426a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell MotionEvent cancelEvent = null; 427a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 42888cccf6c76b6a1c2d67152c2de5599f3c8301b18Chris Banes final int action = MotionEventCompat.getActionMasked(ev); 429a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 430d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes if (mBehaviorTouchView != null || (cancelSuper = performIntercept(ev, TYPE_ON_TOUCH))) { 431a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Safe since performIntercept guarantees that 432a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // mBehaviorTouchView != null if it returns true 433ecc58a45a7bdd60d9b71e6c413b80a3f8cf85822Chris Banes final LayoutParams lp = (LayoutParams) mBehaviorTouchView.getLayoutParams(); 434ecc58a45a7bdd60d9b71e6c413b80a3f8cf85822Chris Banes final Behavior b = lp.getBehavior(); 435ecc58a45a7bdd60d9b71e6c413b80a3f8cf85822Chris Banes if (b != null) { 436d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes handled = b.onTouchEvent(this, mBehaviorTouchView, ev); 437ecc58a45a7bdd60d9b71e6c413b80a3f8cf85822Chris Banes } 438a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 439a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 440a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Keep the super implementation correct 441a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mBehaviorTouchView == null) { 442a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell handled |= super.onTouchEvent(ev); 443a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else if (cancelSuper) { 444a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (cancelEvent != null) { 445a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final long now = SystemClock.uptimeMillis(); 446a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell cancelEvent = MotionEvent.obtain(now, now, 447a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0); 448a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 449a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell super.onTouchEvent(cancelEvent); 450a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 451a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 452a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (!handled && action == MotionEvent.ACTION_DOWN) { 453a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 454a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 455a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 456a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (cancelEvent != null) { 457a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell cancelEvent.recycle(); 458a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 459a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 460a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { 4615cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell resetTouchBehaviors(); 462a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 463a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 464a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return handled; 465a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 466a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 467a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 468a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) { 469a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell super.requestDisallowInterceptTouchEvent(disallowIntercept); 470a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (disallowIntercept) { 4715cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell resetTouchBehaviors(); 472a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 473a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 474a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 475a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private int getKeyline(int index) { 476a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mKeylines == null) { 477a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Log.e(TAG, "No keylines defined for " + this + " - attempted index lookup " + index); 478a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return 0; 479a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 480a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 481a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (index < 0 || index >= mKeylines.length) { 482a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Log.e(TAG, "Keyline index " + index + " out of range for " + this); 483a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return 0; 484a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 485a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 486a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return mKeylines[index]; 487a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 488a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 489a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell static Behavior parseBehavior(Context context, AttributeSet attrs, String name) { 490a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (TextUtils.isEmpty(name)) { 491a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return null; 492a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 493a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 494a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final String fullName; 495a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (name.startsWith(".")) { 496a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Relative to the app package. Prepend the app package name. 497a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell fullName = context.getPackageName() + name; 498a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else if (name.indexOf('.') >= 0) { 499a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Fully qualified package name. 500a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell fullName = name; 501a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else { 502a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Assume stock behavior in this package. 503a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell fullName = WIDGET_PACKAGE_NAME + '.' + name; 504a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 505a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 506a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell try { 507a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Map<String, Constructor<Behavior>> constructors = sConstructors.get(); 508a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (constructors == null) { 509a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell constructors = new HashMap<>(); 510a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell sConstructors.set(constructors); 511a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 512a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Constructor<Behavior> c = constructors.get(fullName); 513a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (c == null) { 514a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Class<Behavior> clazz = (Class<Behavior>) Class.forName(fullName, true, 515a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell context.getClassLoader()); 516a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell c = clazz.getConstructor(CONSTRUCTOR_PARAMS); 517878384f1e6de7bd9196958224ced1ecfca3be6a7Chris Banes c.setAccessible(true); 518a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell constructors.put(fullName, c); 519a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 520a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return c.newInstance(context, attrs); 521a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } catch (Exception e) { 522a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell throw new RuntimeException("Could not inflate Behavior subclass " + fullName, e); 523a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 524a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 525a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 526a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell LayoutParams getResolvedLayoutParams(View child) { 527a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams result = (LayoutParams) child.getLayoutParams(); 528a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (!result.mBehaviorResolved) { 52942058bc54bdb89b9c9429bf6cbd3260787cf0523Adam Powell Class<?> childClass = child.getClass(); 53042058bc54bdb89b9c9429bf6cbd3260787cf0523Adam Powell DefaultBehavior defaultBehavior = null; 53142058bc54bdb89b9c9429bf6cbd3260787cf0523Adam Powell while (childClass != null && 53242058bc54bdb89b9c9429bf6cbd3260787cf0523Adam Powell (defaultBehavior = childClass.getAnnotation(DefaultBehavior.class)) == null) { 53342058bc54bdb89b9c9429bf6cbd3260787cf0523Adam Powell childClass = childClass.getSuperclass(); 53442058bc54bdb89b9c9429bf6cbd3260787cf0523Adam Powell } 535a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (defaultBehavior != null) { 536a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell try { 537a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell result.setBehavior(defaultBehavior.value().newInstance()); 538a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } catch (Exception e) { 539a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Log.e(TAG, "Default behavior class " + defaultBehavior.value().getName() + 540a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell " could not be instantiated. Did you forget a default constructor?", e); 541a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 542a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 543a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell result.mBehaviorResolved = true; 544a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 545a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return result; 546a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 547a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 548a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private void prepareChildren() { 549a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childCount = getChildCount(); 550a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 551a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean resortRequired = mDependencySortedChildren.size() != childCount; 552a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 553a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int i = 0; i < childCount; i++) { 554a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final View child = getChildAt(i); 555a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = getResolvedLayoutParams(child); 556a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (!resortRequired && lp.isDirty(this, child)) { 557a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell resortRequired = true; 558a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 559a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell lp.findAnchorView(this, child); 560a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 561a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 562a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (resortRequired) { 563a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mDependencySortedChildren.clear(); 564a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int i = 0; i < childCount; i++) { 565a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mDependencySortedChildren.add(getChildAt(i)); 566a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 567a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Collections.sort(mDependencySortedChildren, mLayoutDependencyComparator); 568a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 569a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 570a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 571a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 572a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Retrieve the transformed bounding rect of an arbitrary descendant view. 573a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * This does not need to be a direct child. 574a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 575a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param descendant descendant view to reference 576a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param out rect to set to the bounds of the descendant view 577a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 578a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void getDescendantRect(View descendant, Rect out) { 579a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes ViewGroupUtils.getDescendantRect(this, descendant, out); 580a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 581a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 582a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 583a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell protected int getSuggestedMinimumWidth() { 584a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return Math.max(super.getSuggestedMinimumWidth(), getPaddingLeft() + getPaddingRight()); 585a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 586a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 587a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 588a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell protected int getSuggestedMinimumHeight() { 589a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return Math.max(super.getSuggestedMinimumHeight(), getPaddingTop() + getPaddingBottom()); 590a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 591a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 592a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 593a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Called to measure each individual child view unless a 594a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link CoordinatorLayout.Behavior Behavior} is present. The Behavior may choose to delegate 595a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * child measurement to this method. 596a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 597a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child to measure 598a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parentWidthMeasureSpec the width requirements for this view 599a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param widthUsed extra space that has been used up by the parent 600a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * horizontally (possibly by other children of the parent) 601a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parentHeightMeasureSpec the height requirements for this view 602a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param heightUsed extra space that has been used up by the parent 603a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * vertically (possibly by other children of the parent) 604a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 605a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public void onMeasureChild(View child, int parentWidthMeasureSpec, int widthUsed, 606a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int parentHeightMeasureSpec, int heightUsed) { 607a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell measureChildWithMargins(child, parentWidthMeasureSpec, widthUsed, 608a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell parentHeightMeasureSpec, heightUsed); 609a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 610a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 611a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 612a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 613a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell prepareChildren(); 614a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell ensurePreDrawListener(); 615a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 616a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int paddingLeft = getPaddingLeft(); 617a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int paddingTop = getPaddingTop(); 618a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int paddingRight = getPaddingRight(); 619a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int paddingBottom = getPaddingBottom(); 620a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int layoutDirection = ViewCompat.getLayoutDirection(this); 621a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final boolean isRtl = layoutDirection == ViewCompat.LAYOUT_DIRECTION_RTL; 622a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int widthMode = MeasureSpec.getMode(widthMeasureSpec); 623a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int widthSize = MeasureSpec.getSize(widthMeasureSpec); 62475284fffafacd32f4d178020050589f9e70e5ed9Chris Banes final int heightMode = MeasureSpec.getMode(heightMeasureSpec); 62575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes final int heightSize = MeasureSpec.getSize(heightMeasureSpec); 626a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 627a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int widthPadding = paddingLeft + paddingRight; 628a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int heightPadding = paddingTop + paddingBottom; 629a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int widthUsed = getSuggestedMinimumWidth(); 630a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int heightUsed = getSuggestedMinimumHeight(); 631a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int childState = 0; 632a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 63375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes final boolean applyInsets = mLastInsets != null && ViewCompat.getFitsSystemWindows(this); 63475284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 635a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childCount = mDependencySortedChildren.size(); 636a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int i = 0; i < childCount; i++) { 637a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final View child = mDependencySortedChildren.get(i); 638a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 639a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 640a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int keylineWidthUsed = 0; 641a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (lp.keyline >= 0 && widthMode != MeasureSpec.UNSPECIFIED) { 642a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int keylinePos = getKeyline(lp.keyline); 643a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int keylineGravity = GravityCompat.getAbsoluteGravity( 644a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell resolveKeylineGravity(lp.gravity), layoutDirection) 645a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell & Gravity.HORIZONTAL_GRAVITY_MASK; 646a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if ((keylineGravity == Gravity.LEFT && !isRtl) 647a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell || (keylineGravity == Gravity.RIGHT && isRtl)) { 648a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell keylineWidthUsed = Math.max(0, widthSize - paddingRight - keylinePos); 649a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else if ((keylineGravity == Gravity.RIGHT && !isRtl) 650a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell || (keylineGravity == Gravity.LEFT && isRtl)) { 651a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell keylineWidthUsed = Math.max(0, keylinePos - paddingLeft); 652a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 653a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 654a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 65575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes int childWidthMeasureSpec = widthMeasureSpec; 65675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes int childHeightMeasureSpec = heightMeasureSpec; 65775284fffafacd32f4d178020050589f9e70e5ed9Chris Banes if (applyInsets && !ViewCompat.getFitsSystemWindows(child)) { 65875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes // We're set to handle insets but this child isn't, so we will measure the 65975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes // child as if there are no insets 66075284fffafacd32f4d178020050589f9e70e5ed9Chris Banes final int horizInsets = mLastInsets.getSystemWindowInsetLeft() 66175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes + mLastInsets.getSystemWindowInsetRight(); 66275284fffafacd32f4d178020050589f9e70e5ed9Chris Banes final int vertInsets = mLastInsets.getSystemWindowInsetTop() 66375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes + mLastInsets.getSystemWindowInsetBottom(); 66475284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 66575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes childWidthMeasureSpec = MeasureSpec.makeMeasureSpec( 66675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes widthSize - horizInsets, widthMode); 66775284fffafacd32f4d178020050589f9e70e5ed9Chris Banes childHeightMeasureSpec = MeasureSpec.makeMeasureSpec( 66875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes heightSize - vertInsets, heightMode); 66975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 67075284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 671a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Behavior b = lp.getBehavior(); 67275284fffafacd32f4d178020050589f9e70e5ed9Chris Banes if (b == null || !b.onMeasureChild(this, child, childWidthMeasureSpec, keylineWidthUsed, 67375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes childHeightMeasureSpec, 0)) { 67475284fffafacd32f4d178020050589f9e70e5ed9Chris Banes onMeasureChild(child, childWidthMeasureSpec, keylineWidthUsed, 67575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes childHeightMeasureSpec, 0); 676a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 677a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 678a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell widthUsed = Math.max(widthUsed, widthPadding + child.getMeasuredWidth() + 679a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell lp.leftMargin + lp.rightMargin); 680a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 681a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell heightUsed = Math.max(heightUsed, heightPadding + child.getMeasuredHeight() + 682a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell lp.topMargin + lp.bottomMargin); 683a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell childState = ViewCompat.combineMeasuredStates(childState, 684a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell ViewCompat.getMeasuredState(child)); 685a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 686a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 687a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int width = ViewCompat.resolveSizeAndState(widthUsed, widthMeasureSpec, 688a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell childState & ViewCompat.MEASURED_STATE_MASK); 689a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int height = ViewCompat.resolveSizeAndState(heightUsed, heightMeasureSpec, 690a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell childState << ViewCompat.MEASURED_HEIGHT_STATE_SHIFT); 691a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell setMeasuredDimension(width, height); 692a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 693a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 69475284fffafacd32f4d178020050589f9e70e5ed9Chris Banes private void dispatchChildApplyWindowInsets(WindowInsetsCompat insets) { 69575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes if (insets.isConsumed()) { 69675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes return; 69775284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 69875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 69975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes for (int i = 0, z = getChildCount(); i < z; i++) { 70075284fffafacd32f4d178020050589f9e70e5ed9Chris Banes final View child = getChildAt(i); 70175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes if (ViewCompat.getFitsSystemWindows(child)) { 70275284fffafacd32f4d178020050589f9e70e5ed9Chris Banes final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 70375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes final Behavior b = lp.getBehavior(); 70475284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 70575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes if (b != null) { 70675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes // If the view has a behavior, let it try first 70775284fffafacd32f4d178020050589f9e70e5ed9Chris Banes insets = b.onApplyWindowInsets(this, child, insets); 70875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes if (insets.isConsumed()) { 70975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes // If it consumed the insets, break 71075284fffafacd32f4d178020050589f9e70e5ed9Chris Banes break; 71175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 71275284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 71375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 71475284fffafacd32f4d178020050589f9e70e5ed9Chris Banes // Now let the view try and consume them 71575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes insets = ViewCompat.dispatchApplyWindowInsets(child, insets); 71675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes if (insets.isConsumed()) { 71775284fffafacd32f4d178020050589f9e70e5ed9Chris Banes break; 71875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 71975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 72075284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 72175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 72275284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 723a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 724a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Called to lay out each individual child view unless a 725a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link CoordinatorLayout.Behavior Behavior} is present. The Behavior may choose to 726a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * delegate child measurement to this method. 727a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 728a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child view to lay out 729a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param layoutDirection the resolved layout direction for the CoordinatorLayout, such as 730a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link ViewCompat#LAYOUT_DIRECTION_LTR} or 731a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link ViewCompat#LAYOUT_DIRECTION_RTL}. 732a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 733a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public void onLayoutChild(View child, int layoutDirection) { 734a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 735a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (lp.checkAnchorChanged()) { 736a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell throw new IllegalStateException("An anchor may not be changed after CoordinatorLayout" 737a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell + " measurement begins before layout is complete."); 738a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 739a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (lp.mAnchorView != null) { 740a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell layoutChildWithAnchor(child, lp.mAnchorView, layoutDirection); 741a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else if (lp.keyline >= 0) { 742a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell layoutChildWithKeyline(child, lp.keyline, layoutDirection); 743a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else { 744a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell layoutChild(child, layoutDirection); 745a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 746a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 747a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 748a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 749a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell protected void onLayout(boolean changed, int l, int t, int r, int b) { 750a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int layoutDirection = ViewCompat.getLayoutDirection(this); 751a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childCount = mDependencySortedChildren.size(); 752a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int i = 0; i < childCount; i++) { 753a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final View child = mDependencySortedChildren.get(i); 754a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 755a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Behavior behavior = lp.getBehavior(); 756a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 757a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (behavior == null || !behavior.onLayoutChild(this, child, layoutDirection)) { 758a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell onLayoutChild(child, layoutDirection); 759a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 760a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 761a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 762a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 76375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes @Override 76475284fffafacd32f4d178020050589f9e70e5ed9Chris Banes public void onDraw(Canvas c) { 76575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes super.onDraw(c); 76675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes if (mDrawStatusBarBackground && mStatusBarBackground != null) { 76775284fffafacd32f4d178020050589f9e70e5ed9Chris Banes final int inset = mLastInsets != null ? mLastInsets.getSystemWindowInsetTop() : 0; 76875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes if (inset > 0) { 76975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes mStatusBarBackground.setBounds(0, 0, getWidth(), inset); 77075284fffafacd32f4d178020050589f9e70e5ed9Chris Banes mStatusBarBackground.draw(c); 77175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 77275284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 77375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 77475284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 775a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 776a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Mark the last known child position rect for the given child view. 777a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * This will be used when checking if a child view's position has changed between frames. 778a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * The rect used here should be one returned by 779a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link #getChildRect(android.view.View, boolean, android.graphics.Rect)}, with translation 780a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * disabled. 781a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 782a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child view to set for 783a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param r rect to set 784a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 785a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void recordLastChildRect(View child, Rect r) { 786a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 787a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell lp.setLastChildRect(r); 788a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 789a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 790a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 791a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Get the last known child rect recorded by 792a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link #recordLastChildRect(android.view.View, android.graphics.Rect)}. 793a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 794a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child view to retrieve from 795a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param out rect to set to the outpur values 796a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 797a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void getLastChildRect(View child, Rect out) { 798a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 799a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell out.set(lp.getLastChildRect()); 800a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 801a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 802a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 803a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Get the position rect for the given child. If the child has currently requested layout 804a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * or has a visibility of GONE. 805a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 806a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child view to check 807a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param transform true to include transformation in the output rect, false to 808a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * only account for the base position 809a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param out rect to set to the output values 810a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 811a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void getChildRect(View child, boolean transform, Rect out) { 812a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (child.isLayoutRequested() || child.getVisibility() == View.GONE) { 813a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell out.set(0, 0, 0, 0); 814a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return; 815a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 816a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (transform) { 817a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getDescendantRect(child, out); 818a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else { 819a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell out.set(child.getLeft(), child.getTop(), child.getRight(), child.getBottom()); 820a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 821a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 822a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 823a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 824a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Calculate the desired child rect relative to an anchor rect, respecting both 825a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * gravity and anchorGravity. 826a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 827a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child view to calculate a rect for 828a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param layoutDirection the desired layout direction for the CoordinatorLayout 829a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param anchorRect rect in CoordinatorLayout coordinates of the anchor view area 830a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param out rect to set to the output values 831a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 832a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void getDesiredAnchoredChildRect(View child, int layoutDirection, Rect anchorRect, Rect out) { 833a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 834a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int absGravity = GravityCompat.getAbsoluteGravity( 835a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell resolveAnchoredChildGravity(lp.gravity), layoutDirection); 836a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int absAnchorGravity = GravityCompat.getAbsoluteGravity( 837a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell resolveGravity(lp.anchorGravity), 838a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell layoutDirection); 839a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 840a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int hgrav = absGravity & Gravity.HORIZONTAL_GRAVITY_MASK; 841a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int vgrav = absGravity & Gravity.VERTICAL_GRAVITY_MASK; 842a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int anchorHgrav = absAnchorGravity & Gravity.HORIZONTAL_GRAVITY_MASK; 843a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int anchorVgrav = absAnchorGravity & Gravity.VERTICAL_GRAVITY_MASK; 844a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 845a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childWidth = child.getMeasuredWidth(); 846a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childHeight = child.getMeasuredHeight(); 847a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 848a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int left; 849a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int top; 850a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 851d09e24f8d4c10e72dee0e435d3289ddd10223aa0Adam Powell // Align to the anchor. This puts us in an assumed right/bottom child view gravity. 852d09e24f8d4c10e72dee0e435d3289ddd10223aa0Adam Powell // If this is not the case we will subtract out the appropriate portion of 853d09e24f8d4c10e72dee0e435d3289ddd10223aa0Adam Powell // the child size below. 854a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell switch (anchorHgrav) { 855a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell default: 856a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.LEFT: 857a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell left = anchorRect.left; 858a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 859a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.RIGHT: 860d09e24f8d4c10e72dee0e435d3289ddd10223aa0Adam Powell left = anchorRect.right; 861a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 862a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.CENTER_HORIZONTAL: 863d09e24f8d4c10e72dee0e435d3289ddd10223aa0Adam Powell left = anchorRect.left + anchorRect.width() / 2; 864a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 865a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 866a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 867a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell switch (anchorVgrav) { 868a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell default: 869a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.TOP: 870a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell top = anchorRect.top; 871a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 872a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.BOTTOM: 873d09e24f8d4c10e72dee0e435d3289ddd10223aa0Adam Powell top = anchorRect.bottom; 874a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 875a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.CENTER_VERTICAL: 876d09e24f8d4c10e72dee0e435d3289ddd10223aa0Adam Powell top = anchorRect.top + anchorRect.height() / 2; 877a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 878a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 879a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 880d09e24f8d4c10e72dee0e435d3289ddd10223aa0Adam Powell // Offset by the child view's gravity itself. The above assumed right/bottom gravity. 881a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell switch (hgrav) { 882a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell default: 883a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.LEFT: 884d09e24f8d4c10e72dee0e435d3289ddd10223aa0Adam Powell left -= childWidth; 885a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 886a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.RIGHT: 887d09e24f8d4c10e72dee0e435d3289ddd10223aa0Adam Powell // Do nothing, we're already in position. 888a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 889a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.CENTER_HORIZONTAL: 890d09e24f8d4c10e72dee0e435d3289ddd10223aa0Adam Powell left -= childWidth / 2; 891a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 892a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 893a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 894a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell switch (vgrav) { 895a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell default: 896a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.TOP: 897d09e24f8d4c10e72dee0e435d3289ddd10223aa0Adam Powell top -= childHeight; 898a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 899a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.BOTTOM: 900d09e24f8d4c10e72dee0e435d3289ddd10223aa0Adam Powell // Do nothing, we're already in position. 901a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 902a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.CENTER_VERTICAL: 903d09e24f8d4c10e72dee0e435d3289ddd10223aa0Adam Powell top -= childHeight / 2; 904a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 905a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 906a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 907a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int width = getWidth(); 908a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int height = getHeight(); 909a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 910a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Obey margins and padding 911a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell left = Math.max(getPaddingLeft() + lp.leftMargin, 912a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Math.min(left, 913a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell width - getPaddingRight() - childWidth - lp.rightMargin)); 914a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell top = Math.max(getPaddingTop() + lp.topMargin, 915a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Math.min(top, 916a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell height - getPaddingBottom() - childHeight - lp.bottomMargin)); 917a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 918a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell out.set(left, top, left + childWidth, top + childHeight); 919a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 920a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 921a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 922a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * CORE ASSUMPTION: anchor has been laid out by the time this is called for a given child view. 923a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 924a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child to lay out 925a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param anchor view to anchor child relative to; already laid out. 926a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param layoutDirection ViewCompat constant for layout direction 927a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 928a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private void layoutChildWithAnchor(View child, View anchor, int layoutDirection) { 929a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 930a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 931a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Rect anchorRect = mTempRect1; 932a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Rect childRect = mTempRect2; 933a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getDescendantRect(anchor, anchorRect); 934a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getDesiredAnchoredChildRect(child, layoutDirection, anchorRect, childRect); 935a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 936a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell child.layout(childRect.left, childRect.top, childRect.right, childRect.bottom); 937a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 938a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 939a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 940a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Lay out a child view with respect to a keyline. 941a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 942a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>The keyline represents a horizontal offset from the unpadded starting edge of 943a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * the CoordinatorLayout. The child's gravity will affect how it is positioned with 944a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * respect to the keyline.</p> 945a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 946a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child to lay out 947a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param keyline offset from the starting edge in pixels of the keyline to align with 948a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param layoutDirection ViewCompat constant for layout direction 949a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 950a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private void layoutChildWithKeyline(View child, int keyline, int layoutDirection) { 951a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 952a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int absGravity = GravityCompat.getAbsoluteGravity( 953a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell resolveKeylineGravity(lp.gravity), layoutDirection); 954a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 955a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int hgrav = absGravity & Gravity.HORIZONTAL_GRAVITY_MASK; 956a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int vgrav = absGravity & Gravity.VERTICAL_GRAVITY_MASK; 957a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int width = getWidth(); 958a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int height = getHeight(); 959a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childWidth = child.getMeasuredWidth(); 960a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childHeight = child.getMeasuredHeight(); 961a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 962a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (layoutDirection == ViewCompat.LAYOUT_DIRECTION_RTL) { 963a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell keyline = width - keyline; 964a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 965a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 966a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int left = getKeyline(keyline) - childWidth; 967a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int top = 0; 968a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 969a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell switch (hgrav) { 970a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell default: 971a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.LEFT: 972a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Nothing to do. 973a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 974a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.RIGHT: 975a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell left += childWidth; 976a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 977a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.CENTER_HORIZONTAL: 978a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell left += childWidth / 2; 979a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 980a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 981a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 982a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell switch (vgrav) { 983a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell default: 984a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.TOP: 985a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Do nothing, we're already in position. 986a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 987a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.BOTTOM: 988a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell top += childHeight; 989a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 990a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.CENTER_VERTICAL: 991a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell top += childHeight / 2; 992a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 993a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 994a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 995a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Obey margins and padding 996a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell left = Math.max(getPaddingLeft() + lp.leftMargin, 997a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Math.min(left, 998a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell width - getPaddingRight() - childWidth - lp.rightMargin)); 999a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell top = Math.max(getPaddingTop() + lp.topMargin, 1000a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Math.min(top, 1001a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell height - getPaddingBottom() - childHeight - lp.bottomMargin)); 1002a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1003a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell child.layout(left, top, left + childWidth, top + childHeight); 1004a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1005a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1006a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1007a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Lay out a child view with no special handling. This will position the child as 1008a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * if it were within a FrameLayout or similar simple frame. 1009a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1010a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child view to lay out 1011a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param layoutDirection ViewCompat constant for the desired layout direction 1012a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1013a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private void layoutChild(View child, int layoutDirection) { 1014a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 1015a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Rect parent = mTempRect1; 1016a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell parent.set(getPaddingLeft() + lp.leftMargin, 1017a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getPaddingTop() + lp.topMargin, 1018a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getWidth() - getPaddingRight() - lp.rightMargin, 1019a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getHeight() - getPaddingBottom() - lp.bottomMargin); 102075284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 102175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes if (mLastInsets != null && ViewCompat.getFitsSystemWindows(this) 102275284fffafacd32f4d178020050589f9e70e5ed9Chris Banes && !ViewCompat.getFitsSystemWindows(child)) { 102375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes // If we're set to handle insets but this child isn't, then it has been measured as 102475284fffafacd32f4d178020050589f9e70e5ed9Chris Banes // if there are no insets. We need to lay it out to match. 102575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes parent.left += mLastInsets.getSystemWindowInsetLeft(); 102675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes parent.top += mLastInsets.getSystemWindowInsetTop(); 102775284fffafacd32f4d178020050589f9e70e5ed9Chris Banes parent.right -= mLastInsets.getSystemWindowInsetRight(); 102875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes parent.bottom -= mLastInsets.getSystemWindowInsetBottom(); 102975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 103075284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 1031a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Rect out = mTempRect2; 1032a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell GravityCompat.apply(resolveGravity(lp.gravity), child.getMeasuredWidth(), 1033a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell child.getMeasuredHeight(), parent, out, layoutDirection); 1034a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell child.layout(out.left, out.top, out.right, out.bottom); 1035a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1036a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1037a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1038a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Return the given gravity value or the default if the passed value is NO_GRAVITY. 1039a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * This should be used for children that are not anchored to another view or a keyline. 1040a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1041a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private static int resolveGravity(int gravity) { 1042a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return gravity == Gravity.NO_GRAVITY ? GravityCompat.START | Gravity.TOP : gravity; 1043a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1044a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1045a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1046a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Return the given gravity value or the default if the passed value is NO_GRAVITY. 1047a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * This should be used for children that are positioned relative to a keyline. 1048a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1049a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private static int resolveKeylineGravity(int gravity) { 1050a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return gravity == Gravity.NO_GRAVITY ? GravityCompat.END | Gravity.TOP : gravity; 1051a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1052a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1053a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1054a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Return the given gravity value or the default if the passed value is NO_GRAVITY. 1055a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * This should be used for children that are anchored to another view. 1056a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1057a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private static int resolveAnchoredChildGravity(int gravity) { 1058a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return gravity == Gravity.NO_GRAVITY ? Gravity.CENTER : gravity; 1059a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1060a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1061a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 1062a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell protected boolean drawChild(Canvas canvas, View child, long drawingTime) { 1063a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 1064a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (lp.mBehavior != null && lp.mBehavior.getScrimOpacity(this, child) > 0.f) { 1065a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mScrimPaint == null) { 1066a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mScrimPaint = new Paint(); 1067a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1068a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mScrimPaint.setColor(lp.mBehavior.getScrimColor(this, child)); 1069a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1070a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // TODO: Set the clip appropriately to avoid unnecessary overdraw. 1071a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell canvas.drawRect(getPaddingLeft(), getPaddingTop(), 1072a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getWidth() - getPaddingRight(), getHeight() - getPaddingBottom(), mScrimPaint); 1073a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1074a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return super.drawChild(canvas, child, drawingTime); 1075a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1076a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1077a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1078a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * Dispatch any dependent view changes to the relevant {@link Behavior} instances. 1079a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * 1080a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * Usually run as part of the pre-draw step when at least one child view has a reported 1081a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * dependency on another view. This allows CoordinatorLayout to account for layout 1082a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * changes and animations that occur outside of the normal layout pass. 1083a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1084a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * It can also be ran as part of the nested scrolling dispatch to ensure that any offsetting 1085a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * is completed within the correct coordinate window. 1086a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * 1087a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * The offsetting behavior implemented here does not store the computed offset in 1088a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * the LayoutParams; instead it expects that the layout process will always reconstruct 1089a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * the proper positioning. 1090a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * 1091a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * @param fromNestedScroll true if this is being called from one of the nested scroll methods, 1092a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * false if run as part of the pre-draw step. 1093a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1094a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes void dispatchOnDependentViewChanged(final boolean fromNestedScroll) { 1095a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int layoutDirection = ViewCompat.getLayoutDirection(this); 1096a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childCount = mDependencySortedChildren.size(); 1097a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int i = 0; i < childCount; i++) { 1098a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final View child = mDependencySortedChildren.get(i); 1099a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 1100a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1101a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Check child views before for anchor 1102a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int j = 0; j < i; j++) { 1103a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final View checkChild = mDependencySortedChildren.get(j); 1104a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1105a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (lp.mAnchorDirectChild == checkChild) { 1106a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell offsetChildToAnchor(child, layoutDirection); 1107a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1108a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1109a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1110a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Did it change? if not continue 1111a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Rect oldRect = mTempRect1; 1112a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Rect newRect = mTempRect2; 1113a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getLastChildRect(child, oldRect); 1114b7f9224b1495db47eb8fd813b5912250e900770aChris Banes getChildRect(child, true, newRect); 1115a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (oldRect.equals(newRect)) { 1116a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell continue; 1117a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1118a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell recordLastChildRect(child, newRect); 1119a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1120a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Update any behavior-dependent views for the change 1121a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int j = i + 1; j < childCount; j++) { 1122a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final View checkChild = mDependencySortedChildren.get(j); 1123a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams checkLp = (LayoutParams) checkChild.getLayoutParams(); 1124a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Behavior b = checkLp.getBehavior(); 1125a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1126a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (b != null && b.layoutDependsOn(this, checkChild, child)) { 1127a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes if (!fromNestedScroll && checkLp.getChangedAfterNestedScroll()) { 1128a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes // If this is not from a nested scroll and we have already been changed 1129a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes // from a nested scroll, skip the dispatch and reset the flag 1130a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes checkLp.resetChangedAfterNestedScroll(); 1131a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes continue; 1132a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1133a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 1134a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes final boolean handled = b.onDependentViewChanged(this, checkChild, child); 1135a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 1136a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes if (fromNestedScroll) { 1137a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes // If this is from a nested scroll, set the flag so that we may skip 1138a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes // any resulting onPreDraw dispatch (if needed) 1139a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes checkLp.setChangedAfterNestedScroll(handled); 1140a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1141a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1142a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1143a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1144a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1145a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 11460b00489086b22c9688c8c04990dadf54489d45e3Chris Banes void dispatchDependentViewRemoved(View removedChild) { 11470b00489086b22c9688c8c04990dadf54489d45e3Chris Banes final int childCount = getChildCount(); 11480b00489086b22c9688c8c04990dadf54489d45e3Chris Banes for (int i = 0; i < childCount; i++) { 11490b00489086b22c9688c8c04990dadf54489d45e3Chris Banes final View child = getChildAt(i); 11500b00489086b22c9688c8c04990dadf54489d45e3Chris Banes final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 11510b00489086b22c9688c8c04990dadf54489d45e3Chris Banes final Behavior b = lp.getBehavior(); 11520b00489086b22c9688c8c04990dadf54489d45e3Chris Banes 11530b00489086b22c9688c8c04990dadf54489d45e3Chris Banes if (b != null && b.layoutDependsOn(this, child, removedChild)) { 11540b00489086b22c9688c8c04990dadf54489d45e3Chris Banes b.onDependentViewRemoved(this, child, removedChild); 11550b00489086b22c9688c8c04990dadf54489d45e3Chris Banes } 11560b00489086b22c9688c8c04990dadf54489d45e3Chris Banes } 11570b00489086b22c9688c8c04990dadf54489d45e3Chris Banes } 11580b00489086b22c9688c8c04990dadf54489d45e3Chris Banes 1159a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes /** 1160a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * Allows the caller to manually dispatch 1161a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * {@link Behavior#onDependentViewChanged(CoordinatorLayout, View, View)} to the associated 1162a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * {@link Behavior} instances of views which depend on the provided {@link View}. 1163a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * 1164a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * <p>You should not normally need to call this method as the it will be automatically done 1165a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * when the view has changed. 1166a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * 1167a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * @param view the View to find dependents of to dispatch the call. 1168a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes */ 1169a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes public void dispatchDependentViewsChanged(View view) { 1170a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes final int childCount = mDependencySortedChildren.size(); 1171a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes boolean viewSeen = false; 1172a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes for (int i = 0; i < childCount; i++) { 1173a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes final View child = mDependencySortedChildren.get(i); 1174a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes if (child == view) { 1175a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes // We've seen our view, which means that any Views after this could be dependent 1176a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes viewSeen = true; 1177a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes continue; 1178a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1179a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes if (viewSeen) { 1180a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams) 1181a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes child.getLayoutParams(); 1182a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes CoordinatorLayout.Behavior b = lp.getBehavior(); 1183a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes if (b != null && lp.dependsOn(this, child, view)) { 1184a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes b.onDependentViewChanged(this, child, view); 1185a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1186a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1187a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1188a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1189a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1190a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1191a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * Returns the list of views which the provided view depends on. Do not store this list as it's 1192a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * contents may not be valid beyond the caller. 1193a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * 1194a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * @param child the view to find dependencies for. 1195a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * 1196a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * @return the list of views which {@code child} depends on. 1197a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes */ 1198a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes public List<View> getDependencies(View child) { 1199a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes // TODO The result of this is probably a good candidate for caching 1200a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 1201a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 1202a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes final List<View> list = mTempDependenciesList; 1203a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes list.clear(); 1204a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 1205a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes final int childCount = getChildCount(); 1206a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes for (int i = 0; i < childCount; i++) { 1207a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes final View other = getChildAt(i); 1208a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes if (other == child) { 1209a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes continue; 1210a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1211a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes if (lp.dependsOn(this, child, other)) { 1212a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes list.add(other); 1213a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1214a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1215a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 1216a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes return list; 1217a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1218a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 1219a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes /** 1220a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Add or remove the pre-draw listener as necessary. 1221a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1222a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void ensurePreDrawListener() { 1223a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean hasDependencies = false; 1224a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childCount = getChildCount(); 1225a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int i = 0; i < childCount; i++) { 1226a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final View child = getChildAt(i); 1227a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (hasDependencies(child)) { 1228a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell hasDependencies = true; 1229a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 1230a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1231a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1232a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1233a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (hasDependencies != mNeedsPreDrawListener) { 1234a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (hasDependencies) { 1235a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell addPreDrawListener(); 1236a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else { 1237a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell removePreDrawListener(); 1238a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1239a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1240a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1241a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1242a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1243a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Check if the given child has any layout dependencies on other child views. 1244a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1245a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean hasDependencies(View child) { 1246a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 1247a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (lp.mAnchorView != null) { 1248a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return true; 1249a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1250a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1251a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childCount = getChildCount(); 1252a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int i = 0; i < childCount; i++) { 1253a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final View other = getChildAt(i); 1254a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (other == child) { 1255a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell continue; 1256a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1257a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (lp.dependsOn(this, child, other)) { 1258a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return true; 1259a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1260a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1261a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return false; 1262a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1263a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1264a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1265a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Add the pre-draw listener if we're attached to a window and mark that we currently 1266a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * need it when attached. 1267a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1268a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void addPreDrawListener() { 1269a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mIsAttachedToWindow) { 1270a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Add the listener 1271a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mOnPreDrawListener == null) { 1272a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mOnPreDrawListener = new OnPreDrawListener(); 1273a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1274a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final ViewTreeObserver vto = getViewTreeObserver(); 1275a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell vto.addOnPreDrawListener(mOnPreDrawListener); 1276a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1277a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1278a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Record that we need the listener regardless of whether or not we're attached. 1279a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // We'll add the real listener when we become attached. 1280a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mNeedsPreDrawListener = true; 1281a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1282a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1283a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1284a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Remove the pre-draw listener if we're attached to a window and mark that we currently 1285a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * do not need it when attached. 1286a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1287a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void removePreDrawListener() { 1288a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mIsAttachedToWindow) { 1289a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mOnPreDrawListener != null) { 1290a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final ViewTreeObserver vto = getViewTreeObserver(); 1291a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell vto.removeOnPreDrawListener(mOnPreDrawListener); 1292a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1293a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1294a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mNeedsPreDrawListener = false; 1295a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1296a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1297a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1298a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Adjust the child left, top, right, bottom rect to the correct anchor view position, 1299a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * respecting gravity and anchor gravity. 1300a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1301a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Note that child translation properties are ignored in this process, allowing children 1302a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * to be animated away from their anchor. However, if the anchor view is animated, 1303a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * the child will be offset to match the anchor's translated position. 1304a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1305a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void offsetChildToAnchor(View child, int layoutDirection) { 1306a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 1307a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (lp.mAnchorView != null) { 1308a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Rect anchorRect = mTempRect1; 1309a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Rect childRect = mTempRect2; 1310a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Rect desiredChildRect = mTempRect3; 1311a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1312a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getDescendantRect(lp.mAnchorView, anchorRect); 1313a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getChildRect(child, false, childRect); 1314a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getDesiredAnchoredChildRect(child, layoutDirection, anchorRect, desiredChildRect); 1315a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1316a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int dx = desiredChildRect.left - childRect.left; 1317a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int dy = desiredChildRect.top - childRect.top; 1318a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1319a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (dx != 0) { 1320a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell child.offsetLeftAndRight(dx); 1321a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1322a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (dy != 0) { 1323a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell child.offsetTopAndBottom(dy); 1324a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1325a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 1326a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes if (dx != 0 || dy != 0) { 1327a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes // If we have needed to move, make sure to notify the child's Behavior 1328a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes final Behavior b = lp.getBehavior(); 1329a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes if (b != null) { 1330a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes b.onDependentViewChanged(this, child, lp.mAnchorView); 1331a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1332a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1333a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1334a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1335a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1336a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1337a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Check if a given point in the CoordinatorLayout's coordinates are within the view bounds 1338a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * of the given direct child view. 1339a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1340a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child view to test 1341a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param x X coordinate to test, in the CoordinatorLayout's coordinate system 1342a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param y Y coordinate to test, in the CoordinatorLayout's coordinate system 1343a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true if the point is within the child view's bounds, false otherwise 1344a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1345a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean isPointInChildBounds(View child, int x, int y) { 1346a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Rect r = mTempRect1; 1347a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getDescendantRect(child, r); 1348a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return r.contains(x, y); 1349a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1350a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1351b7f9224b1495db47eb8fd813b5912250e900770aChris Banes /** 1352b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * Check whether two views overlap each other. The views need to be descendants of this 1353b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * {@link CoordinatorLayout} in the view hierarchy. 1354b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * 1355b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * @param first first child view to test 1356b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * @param second second child view to test 1357b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * @return true if both views are visible and overlap each other 1358b7f9224b1495db47eb8fd813b5912250e900770aChris Banes */ 1359b7f9224b1495db47eb8fd813b5912250e900770aChris Banes public boolean doViewsOverlap(View first, View second) { 1360b7f9224b1495db47eb8fd813b5912250e900770aChris Banes if (first.getVisibility() == VISIBLE && second.getVisibility() == VISIBLE) { 1361b7f9224b1495db47eb8fd813b5912250e900770aChris Banes final Rect firstRect = mTempRect1; 1362b7f9224b1495db47eb8fd813b5912250e900770aChris Banes getChildRect(first, first.getParent() != this, firstRect); 1363b7f9224b1495db47eb8fd813b5912250e900770aChris Banes final Rect secondRect = mTempRect2; 1364b7f9224b1495db47eb8fd813b5912250e900770aChris Banes getChildRect(second, second.getParent() != this, secondRect); 1365b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 1366b7f9224b1495db47eb8fd813b5912250e900770aChris Banes return !(firstRect.left > secondRect.right || firstRect.top > secondRect.bottom 1367b7f9224b1495db47eb8fd813b5912250e900770aChris Banes || firstRect.right < secondRect.left || firstRect.bottom < secondRect.top); 1368b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 1369b7f9224b1495db47eb8fd813b5912250e900770aChris Banes return false; 1370b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 1371b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 1372a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 1373a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public LayoutParams generateLayoutParams(AttributeSet attrs) { 1374a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return new LayoutParams(getContext(), attrs); 1375a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1376a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1377a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 1378a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { 1379a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (p instanceof LayoutParams) { 1380a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return new LayoutParams((LayoutParams) p); 1381a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else if (p instanceof MarginLayoutParams) { 1382a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return new LayoutParams((MarginLayoutParams) p); 1383a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1384a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return new LayoutParams(p); 1385a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1386a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1387a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 1388a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell protected LayoutParams generateDefaultLayoutParams() { 1389a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); 1390a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1391a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1392a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 1393a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { 1394a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return p instanceof LayoutParams && super.checkLayoutParams(p); 1395a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1396a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1397a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) { 13985cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell boolean handled = false; 13995cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 14005cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final int childCount = getChildCount(); 14015cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell for (int i = 0; i < childCount; i++) { 14025cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final View view = getChildAt(i); 14035cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final LayoutParams lp = (LayoutParams) view.getLayoutParams(); 14045cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final Behavior viewBehavior = lp.getBehavior(); 14055cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (viewBehavior != null) { 14065cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final boolean accepted = viewBehavior.onStartNestedScroll(this, view, child, target, 14075cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell nestedScrollAxes); 14085cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell handled |= accepted; 14095cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 14105cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell lp.acceptNestedScroll(accepted); 14115cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } else { 14125cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell lp.acceptNestedScroll(false); 14135cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 14145cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 14155cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell return handled; 1416a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1417a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1418a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public void onNestedScrollAccepted(View child, View target, int nestedScrollAxes) { 1419a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mNestedScrollingParentHelper.onNestedScrollAccepted(child, target, nestedScrollAxes); 14205cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell mNestedScrollingDirectChild = child; 14215cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell mNestedScrollingTarget = target; 14225cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 14235cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final int childCount = getChildCount(); 14245cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell for (int i = 0; i < childCount; i++) { 14255cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final View view = getChildAt(i); 14265cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final LayoutParams lp = (LayoutParams) view.getLayoutParams(); 14275cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (!lp.isNestedScrollAccepted()) { 14285cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell continue; 14295cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 14305cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 14315cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final Behavior viewBehavior = lp.getBehavior(); 14325cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (viewBehavior != null) { 14335cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell viewBehavior.onNestedScrollAccepted(this, view, child, target, nestedScrollAxes); 14345cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 14355cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 1436a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1437a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1438a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public void onStopNestedScroll(View target) { 1439a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mNestedScrollingParentHelper.onStopNestedScroll(target); 14405cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 14415cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final int childCount = getChildCount(); 14425cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell for (int i = 0; i < childCount; i++) { 14435cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final View view = getChildAt(i); 14445cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final LayoutParams lp = (LayoutParams) view.getLayoutParams(); 14455cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (!lp.isNestedScrollAccepted()) { 14465cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell continue; 14475cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 14485cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 14495cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final Behavior viewBehavior = lp.getBehavior(); 14505cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (viewBehavior != null) { 14515cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell viewBehavior.onStopNestedScroll(this, view, target); 14525cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 14535cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell lp.resetNestedScroll(); 1454a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes lp.resetChangedAfterNestedScroll(); 14555cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 14565cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 14575cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell mNestedScrollingDirectChild = null; 14585cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell mNestedScrollingTarget = null; 1459a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1460a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1461a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public void onNestedScroll(View target, int dxConsumed, int dyConsumed, 1462a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int dxUnconsumed, int dyUnconsumed) { 14635cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final int childCount = getChildCount(); 1464a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes boolean accepted = false; 1465a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 14665cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell for (int i = 0; i < childCount; i++) { 14675cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final View view = getChildAt(i); 14685cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final LayoutParams lp = (LayoutParams) view.getLayoutParams(); 14695cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (!lp.isNestedScrollAccepted()) { 14705cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell continue; 14715cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 14725cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 14735cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final Behavior viewBehavior = lp.getBehavior(); 14745cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (viewBehavior != null) { 14755cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell viewBehavior.onNestedScroll(this, view, target, dxConsumed, dyConsumed, 14765cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell dxUnconsumed, dyUnconsumed); 1477a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes accepted = true; 14785cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 14795cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 1480a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 1481a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes if (accepted) { 1482a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes dispatchOnDependentViewChanged(true); 1483a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1484a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1485a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1486a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) { 14875cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell int xConsumed = 0; 14885cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell int yConsumed = 0; 1489a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes boolean accepted = false; 14905cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 14915cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final int childCount = getChildCount(); 14925cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell for (int i = 0; i < childCount; i++) { 14935cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final View view = getChildAt(i); 14945cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final LayoutParams lp = (LayoutParams) view.getLayoutParams(); 14955cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (!lp.isNestedScrollAccepted()) { 14965cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell continue; 14975cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 14985cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 14995cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final Behavior viewBehavior = lp.getBehavior(); 15005cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (viewBehavior != null) { 15015cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell mTempIntPair[0] = mTempIntPair[1] = 0; 15025cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell viewBehavior.onNestedPreScroll(this, view, target, dx, dy, mTempIntPair); 15035cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 15045cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell xConsumed = dx > 0 ? Math.max(xConsumed, mTempIntPair[0]) 15055cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell : Math.min(xConsumed, mTempIntPair[0]); 15065cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell yConsumed = dy > 0 ? Math.max(yConsumed, mTempIntPair[1]) 15075cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell : Math.min(yConsumed, mTempIntPair[1]); 1508a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 1509a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes accepted = true; 15105cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 15115cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 15125cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 15135cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell consumed[0] = xConsumed; 15145cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell consumed[1] = yConsumed; 1515a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 1516a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes if (accepted) { 1517a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes dispatchOnDependentViewChanged(true); 1518a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1519a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1520a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1521a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) { 15225cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell boolean handled = false; 15235cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 15245cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final int childCount = getChildCount(); 15255cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell for (int i = 0; i < childCount; i++) { 15265cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final View view = getChildAt(i); 15275cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final LayoutParams lp = (LayoutParams) view.getLayoutParams(); 15285cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (!lp.isNestedScrollAccepted()) { 15295cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell continue; 15305cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 15315cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 15325cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final Behavior viewBehavior = lp.getBehavior(); 15335cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (viewBehavior != null) { 15345cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell handled |= viewBehavior.onNestedFling(this, view, target, velocityX, velocityY, 15355cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell consumed); 15365cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 15375cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 1538a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes if (handled) { 1539a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes dispatchOnDependentViewChanged(true); 1540a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 15415cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell return handled; 1542a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1543a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1544a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean onNestedPreFling(View target, float velocityX, float velocityY) { 15455cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell boolean handled = false; 15465cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 15475cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final int childCount = getChildCount(); 15485cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell for (int i = 0; i < childCount; i++) { 15495cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final View view = getChildAt(i); 15505cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final LayoutParams lp = (LayoutParams) view.getLayoutParams(); 15515cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (!lp.isNestedScrollAccepted()) { 15525cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell continue; 15535cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 15545cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 15555cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final Behavior viewBehavior = lp.getBehavior(); 15565cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (viewBehavior != null) { 15575cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell handled |= viewBehavior.onNestedPreFling(this, view, target, velocityX, velocityY); 15585cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 15595cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 15605cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell return handled; 1561a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1562a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1563a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public int getNestedScrollAxes() { 1564a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return mNestedScrollingParentHelper.getNestedScrollAxes(); 1565a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1566a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1567a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell class OnPreDrawListener implements ViewTreeObserver.OnPreDrawListener { 1568a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 1569a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean onPreDraw() { 1570a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes dispatchOnDependentViewChanged(false); 1571a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return true; 1572a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1573a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1574a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1575a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1576a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Sorts child views with higher Z values to the beginning of a collection. 1577a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1578a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell static class ViewElevationComparator implements Comparator<View> { 1579a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 1580a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public int compare(View lhs, View rhs) { 1581a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final float lz = ViewCompat.getZ(lhs); 1582a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final float rz = ViewCompat.getZ(rhs); 1583a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (lz > rz) { 1584a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return -1; 1585a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else if (lz < rz) { 1586a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return 1; 1587a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1588a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return 0; 1589a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1590a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1591a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1592a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1593a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Defines the default {@link Behavior} of a {@link View} class. 1594a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1595a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>When writing a custom view, use this annotation to define the default behavior 1596a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * when used as a direct child of an {@link CoordinatorLayout}. The default behavior 1597a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * can be overridden using {@link LayoutParams#setBehavior}.</p> 1598a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1599a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>Example: <code>@DefaultBehavior(MyBehavior.class)</code></p> 1600a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1601a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Retention(RetentionPolicy.RUNTIME) 1602a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public @interface DefaultBehavior { 1603a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Class<? extends Behavior> value(); 1604a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1605a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1606a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1607a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Interaction behavior plugin for child views of {@link CoordinatorLayout}. 1608a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1609a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>A Behavior implements one or more interactions that a user can take on a child view. 1610a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * These interactions may include drags, swipes, flings, or any other gestures.</p> 1611a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1612a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param <V> The View type that this Behavior operates on 1613a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1614a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public static abstract class Behavior<V extends View> { 1615a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1616a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1617a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Default constructor for instantiating Behaviors. 1618a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1619a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public Behavior() { 1620a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1621a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1622a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1623a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Default constructor for inflating Behaviors from layout. The Behavior will have 1624a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * the opportunity to parse specially defined layout parameters. These parameters will 1625a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * appear on the child view tag. 1626a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1627a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param context 1628a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param attrs 1629a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1630a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public Behavior(Context context, AttributeSet attrs) { 1631a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1632a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1633a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1634a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Respond to CoordinatorLayout touch events before they are dispatched to child views. 1635a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1636a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>Behaviors can use this to monitor inbound touch events until one decides to 1637a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * intercept the rest of the event stream to take an action on its associated child view. 1638a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * This method will return false until it detects the proper intercept conditions, then 1639a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * return true once those conditions have occurred.</p> 1640a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1641a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>Once a Behavior intercepts touch events, the rest of the event stream will 1642a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * be sent to the {@link #onTouchEvent} method.</p> 1643a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1644a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>The default implementation of this method always returns false.</p> 1645a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1646a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent view currently receiving this touch event 1647a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child view associated with this Behavior 1648a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param ev the MotionEvent describing the touch event being processed 1649a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true if this Behavior would like to intercept and take over the event stream. 1650a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * The default always returns false. 1651a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1652a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean onInterceptTouchEvent(CoordinatorLayout parent, V child, MotionEvent ev) { 1653a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return false; 1654a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1655a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1656a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1657a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Respond to CoordinatorLayout touch events after this Behavior has started 1658a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link #onInterceptTouchEvent intercepting} them. 1659a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1660a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>Behaviors may intercept touch events in order to help the CoordinatorLayout 1661a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * manipulate its child views. For example, a Behavior may allow a user to drag a 1662a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * UI pane open or closed. This method should perform actual mutations of view 1663a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * layout state.</p> 1664a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1665a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent view currently receiving this touch event 1666a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child view associated with this Behavior 1667a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param ev the MotionEvent describing the touch event being processed 1668a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true if this Behavior handled this touch event and would like to continue 1669a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * receiving events in this stream. The default always returns false. 1670a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1671a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean onTouchEvent(CoordinatorLayout parent, V child, MotionEvent ev) { 1672a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return false; 1673a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1674a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1675a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1676a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Supply a scrim color that will be painted behind the associated child view. 1677a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1678a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>A scrim may be used to indicate that the other elements beneath it are not currently 1679a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * interactive or actionable, drawing user focus and attention to the views above the scrim. 1680a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * </p> 1681a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1682a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>The default implementation returns {@link Color#BLACK}.</p> 1683a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1684a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent view of the given child 1685a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child view above the scrim 1686a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return the desired scrim color in 0xAARRGGBB format. The default return value is 1687a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link Color#BLACK}. 1688a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @see #getScrimOpacity(CoordinatorLayout, android.view.View) 1689a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1690a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public final int getScrimColor(CoordinatorLayout parent, V child) { 1691a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return Color.BLACK; 1692a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1693a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1694a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1695a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Determine the current opacity of the scrim behind a given child view 1696a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1697a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>A scrim may be used to indicate that the other elements beneath it are not currently 1698a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * interactive or actionable, drawing user focus and attention to the views above the scrim. 1699a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * </p> 1700a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1701a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>The default implementation returns 0.0f.</p> 1702a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1703a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent view of the given child 1704a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child view above the scrim 1705a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return the desired scrim opacity from 0.0f to 1.0f. The default return value is 0.0f. 1706a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1707a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public final float getScrimOpacity(CoordinatorLayout parent, V child) { 1708a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return 0.f; 1709a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1710a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1711a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1712a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Determine whether interaction with views behind the given child in the child order 1713a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * should be blocked. 1714a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1715a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>The default implementation returns true if 1716a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link #getScrimOpacity(CoordinatorLayout, android.view.View)} would return > 0.0f.</p> 1717a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1718a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent view of the given child 1719a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child view to test 1720a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true if {@link #getScrimOpacity(CoordinatorLayout, android.view.View)} would 1721a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * return > 0.0f. 1722a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1723a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean blocksInteractionBelow(CoordinatorLayout parent, V child) { 1724a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return getScrimOpacity(parent, child) > 0.f; 1725a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1726a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1727a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1728a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Determine whether the supplied child view has another specific sibling view as a 1729a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * layout dependency. 1730a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1731a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>This method will be called at least once in response to a layout request. If it 1732a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * returns true for a given child and dependency view pair, the parent CoordinatorLayout 1733a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * will:</p> 1734a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <ol> 1735a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <li>Always lay out this child after the dependent child is laid out, regardless 1736a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * of child order.</li> 1737a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <li>Call {@link #onDependentViewChanged} when the dependency view's layout or 1738a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * position changes.</li> 1739a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * </ol> 1740a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1741a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent view of the given child 1742a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child view to test 1743a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param dependency the proposed dependency of child 1744a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true if child's layout depends on the proposed dependency's layout, 1745a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * false otherwise 1746a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1747a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @see #onDependentViewChanged(CoordinatorLayout, android.view.View, android.view.View) 1748a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1749a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean layoutDependsOn(CoordinatorLayout parent, V child, View dependency) { 1750a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return false; 1751a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1752a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1753a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1754a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * Respond to a change in a child's dependent view 1755a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * 1756a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * <p>This method is called whenever a dependent view changes in size or position outside 1757a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * of the standard layout flow. A Behavior may use this method to appropriately update 1758a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * the child view in response.</p> 1759a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1760a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * <p>A view's dependency is determined by 1761a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * {@link #layoutDependsOn(CoordinatorLayout, android.view.View, android.view.View)} or 1762a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * if {@code child} has set another view as it's anchor.</p> 1763a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1764a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>Note that if a Behavior changes the layout of a child via this method, it should 1765a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * also be able to reconstruct the correct position in 1766a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link #onLayoutChild(CoordinatorLayout, android.view.View, int) onLayoutChild}. 1767a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <code>onDependentViewChanged</code> will not be called during normal layout since 1768a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * the layout of each child view will always happen in dependency order.</p> 1769a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1770a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>If the Behavior changes the child view's size or position, it should return true. 1771a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * The default implementation returns false.</p> 1772a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1773a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent view of the given child 1774a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child view to manipulate 1775a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param dependency the dependent view that changed 1776a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true if the Behavior changed the child view's size or position, false otherwise 1777a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1778a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean onDependentViewChanged(CoordinatorLayout parent, V child, View dependency) { 1779a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return false; 1780a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1781a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1782a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 17830b00489086b22c9688c8c04990dadf54489d45e3Chris Banes * Respond to a child's dependent view being removed. 17840b00489086b22c9688c8c04990dadf54489d45e3Chris Banes * 17850b00489086b22c9688c8c04990dadf54489d45e3Chris Banes * <p>This method is called after a dependent view has been removed from the parent. 17860b00489086b22c9688c8c04990dadf54489d45e3Chris Banes * A Behavior may use this method to appropriately update the child view in response.</p> 17870b00489086b22c9688c8c04990dadf54489d45e3Chris Banes * 17880b00489086b22c9688c8c04990dadf54489d45e3Chris Banes * <p>A view's dependency is determined by 17890b00489086b22c9688c8c04990dadf54489d45e3Chris Banes * {@link #layoutDependsOn(CoordinatorLayout, android.view.View, android.view.View)} or 17900b00489086b22c9688c8c04990dadf54489d45e3Chris Banes * if {@code child} has set another view as it's anchor.</p> 17910b00489086b22c9688c8c04990dadf54489d45e3Chris Banes * 17920b00489086b22c9688c8c04990dadf54489d45e3Chris Banes * @param parent the parent view of the given child 17930b00489086b22c9688c8c04990dadf54489d45e3Chris Banes * @param child the child view to manipulate 17940b00489086b22c9688c8c04990dadf54489d45e3Chris Banes * @param dependency the dependent view that has been removed 17950b00489086b22c9688c8c04990dadf54489d45e3Chris Banes */ 17960b00489086b22c9688c8c04990dadf54489d45e3Chris Banes public void onDependentViewRemoved(CoordinatorLayout parent, V child, View dependency) { 17970b00489086b22c9688c8c04990dadf54489d45e3Chris Banes } 17980b00489086b22c9688c8c04990dadf54489d45e3Chris Banes 17990b00489086b22c9688c8c04990dadf54489d45e3Chris Banes /** 1800a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Determine whether the given child view should be considered dirty. 1801a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1802a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>If a property determined by the Behavior such as other dependent views would change, 1803a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * the Behavior should report a child view as dirty. This will prompt the CoordinatorLayout 1804a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * to re-query Behavior-determined properties as appropriate.</p> 1805a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1806a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent view of the given child 1807a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child view to check 1808a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true if child is dirty 1809a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1810a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean isDirty(CoordinatorLayout parent, V child) { 1811a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return false; 1812a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1813a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1814a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1815a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Called when the parent CoordinatorLayout is about to measure the given child view. 1816a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1817a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>This method can be used to perform custom or modified measurement of a child view 1818a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * in place of the default child measurement behavior. The Behavior's implementation 1819a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * can delegate to the standard CoordinatorLayout measurement behavior by calling 1820a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link CoordinatorLayout#onMeasureChild(android.view.View, int, int, int, int) 1821a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * parent.onMeasureChild}.</p> 1822a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1823a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent CoordinatorLayout 1824a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child to measure 1825a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parentWidthMeasureSpec the width requirements for this view 1826a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param widthUsed extra space that has been used up by the parent 1827a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * horizontally (possibly by other children of the parent) 1828a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parentHeightMeasureSpec the height requirements for this view 1829a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param heightUsed extra space that has been used up by the parent 1830a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * vertically (possibly by other children of the parent) 1831a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true if the Behavior measured the child view, false if the CoordinatorLayout 1832a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * should perform its default measurement 1833a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1834a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean onMeasureChild(CoordinatorLayout parent, V child, 1835a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int parentWidthMeasureSpec, int widthUsed, 1836a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int parentHeightMeasureSpec, int heightUsed) { 1837a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return false; 1838a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1839a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1840a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1841a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Called when the parent CoordinatorLayout is about the lay out the given child view. 1842a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1843a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>This method can be used to perform custom or modified layout of a child view 1844a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * in place of the default child layout behavior. The Behavior's implementation can 1845a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * delegate to the standard CoordinatorLayout measurement behavior by calling 1846a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link CoordinatorLayout#onLayoutChild(android.view.View, int) 1847a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * parent.onMeasureChild}.</p> 1848a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1849a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>If a Behavior implements 1850a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link #onDependentViewChanged(CoordinatorLayout, android.view.View, android.view.View)} 1851a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * to change the position of a view in response to a dependent view changing, it 1852a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * should also implement <code>onLayoutChild</code> in such a way that respects those 1853a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * dependent views. <code>onLayoutChild</code> will always be called for a dependent view 1854a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <em>after</em> its dependency has been laid out.</p> 1855a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1856a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent CoordinatorLayout 1857a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child view to lay out 1858a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param layoutDirection the resolved layout direction for the CoordinatorLayout, such as 1859a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link ViewCompat#LAYOUT_DIRECTION_LTR} or 1860a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link ViewCompat#LAYOUT_DIRECTION_RTL}. 1861a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true if the Behavior performed layout of the child view, false to request 1862a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * default layout behavior 1863a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1864a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean onLayoutChild(CoordinatorLayout parent, V child, int layoutDirection) { 1865a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return false; 1866a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1867a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1868a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Utility methods for accessing child-specific, behavior-modifiable properties. 1869a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1870a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1871a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Associate a Behavior-specific tag object with the given child view. 1872a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * This object will be stored with the child view's LayoutParams. 1873a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1874a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child view to set tag with 1875a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param tag tag object to set 1876a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1877a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public static void setTag(View child, Object tag) { 1878a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 1879a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell lp.mBehaviorTag = tag; 1880a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1881a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1882a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1883a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Get the behavior-specific tag object with the given child view. 1884a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * This object is stored with the child view's LayoutParams. 1885a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1886a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child view to get tag with 1887a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return the previously stored tag object 1888a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1889a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public static Object getTag(View child) { 1890a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 1891a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return lp.mBehaviorTag; 1892a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 18935cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 18945cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 18955cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell /** 18965cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * Called when a descendant of the CoordinatorLayout attempts to initiate a nested scroll. 18975cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 18985cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p>Any Behavior associated with any direct child of the CoordinatorLayout may respond 18995cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * to this event and return true to indicate that the CoordinatorLayout should act as 19005cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * a nested scrolling parent for this scroll. Only Behaviors that return true from 19015cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * this method will receive subsequent nested scroll events.</p> 19025cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 19035cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is 19045cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * associated with 19055cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param child the child view of the CoordinatorLayout this Behavior is associated with 19065cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param directTargetChild the child view of the CoordinatorLayout that either is or 19075cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * contains the target of the nested scroll operation 19085cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param target the descendant view of the CoordinatorLayout initiating the nested scroll 19095cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param nestedScrollAxes the axes that this nested scroll applies to. See 19105cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * {@link ViewCompat#SCROLL_AXIS_HORIZONTAL}, 19115cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * {@link ViewCompat#SCROLL_AXIS_VERTICAL} 19125cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @return true if the Behavior wishes to accept this nested scroll 19135cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 19145cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @see NestedScrollingParent#onStartNestedScroll(View, View, int) 19155cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell */ 19165cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, 19175cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell V child, View directTargetChild, View target, int nestedScrollAxes) { 19185cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell return false; 19195cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 19205cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 19215cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell /** 19225cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * Called when a nested scroll has been accepted by the CoordinatorLayout. 19235cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 19245cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p>Any Behavior associated with any direct child of the CoordinatorLayout may elect 19255cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * to accept the nested scroll as part of {@link #onStartNestedScroll}. Each Behavior 19265cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * that returned true will receive subsequent nested scroll events for that nested scroll. 19275cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * </p> 19285cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 19295cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is 19305cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * associated with 19315cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param child the child view of the CoordinatorLayout this Behavior is associated with 19325cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param directTargetChild the child view of the CoordinatorLayout that either is or 19335cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * contains the target of the nested scroll operation 19345cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param target the descendant view of the CoordinatorLayout initiating the nested scroll 19355cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param nestedScrollAxes the axes that this nested scroll applies to. See 19365cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * {@link ViewCompat#SCROLL_AXIS_HORIZONTAL}, 19375cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * {@link ViewCompat#SCROLL_AXIS_VERTICAL} 19385cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 19395cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @see NestedScrollingParent#onNestedScrollAccepted(View, View, int) 19405cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell */ 19415cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell public void onNestedScrollAccepted(CoordinatorLayout coordinatorLayout, V child, 19425cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell View directTargetChild, View target, int nestedScrollAxes) { 19435cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell // Do nothing 19445cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 19455cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 19465cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell /** 19475cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * Called when a nested scroll has ended. 19485cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 19495cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p>Any Behavior associated with any direct child of the CoordinatorLayout may elect 19505cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * to accept the nested scroll as part of {@link #onStartNestedScroll}. Each Behavior 19515cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * that returned true will receive subsequent nested scroll events for that nested scroll. 19525cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * </p> 19535cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 19545cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p><code>onStopNestedScroll</code> marks the end of a single nested scroll event 19555cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * sequence. This is a good place to clean up any state related to the nested scroll. 19565cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * </p> 19575cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 19585cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is 19595cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * associated with 19605cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param child the child view of the CoordinatorLayout this Behavior is associated with 19615cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param target the descendant view of the CoordinatorLayout that initiated 19625cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * the nested scroll 19635cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 19645cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @see NestedScrollingParent#onStopNestedScroll(View) 19655cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell */ 19665cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, V child, View target) { 19675cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell // Do nothing 19685cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 19695cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 19705cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell /** 19715cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * Called when a nested scroll in progress has updated and the target has scrolled or 19725cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * attempted to scroll. 19735cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 19745cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p>Any Behavior associated with the direct child of the CoordinatorLayout may elect 19755cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * to accept the nested scroll as part of {@link #onStartNestedScroll}. Each Behavior 19765cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * that returned true will receive subsequent nested scroll events for that nested scroll. 19775cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * </p> 19785cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 19795cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p><code>onNestedScroll</code> is called each time the nested scroll is updated by the 19805cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * nested scrolling child, with both consumed and unconsumed components of the scroll 19815cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * supplied in pixels. <em>Each Behavior responding to the nested scroll will receive the 19825cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * same values.</em> 19835cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * </p> 19845cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 19855cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is 19865cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * associated with 19875cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param child the child view of the CoordinatorLayout this Behavior is associated with 19885cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param target the descendant view of the CoordinatorLayout performing the nested scroll 19895cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param dxConsumed horizontal pixels consumed by the target's own scrolling operation 19905cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param dyConsumed vertical pixels consumed by the target's own scrolling operation 19915cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param dxUnconsumed horizontal pixels not consumed by the target's own scrolling 19925cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * operation, but requested by the user 19935cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param dyUnconsumed vertical pixels not consumed by the target's own scrolling operation, 19945cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * but requested by the user 19955cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 19965cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @see NestedScrollingParent#onNestedScroll(View, int, int, int, int) 19975cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell */ 19985cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell public void onNestedScroll(CoordinatorLayout coordinatorLayout, V child, View target, 19995cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) { 20005cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell // Do nothing 20015cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 20025cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 20035cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell /** 20045cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * Called when a nested scroll in progress is about to update, before the target has 20055cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * consumed any of the scrolled distance. 20065cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 20075cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p>Any Behavior associated with the direct child of the CoordinatorLayout may elect 20085cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * to accept the nested scroll as part of {@link #onStartNestedScroll}. Each Behavior 20095cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * that returned true will receive subsequent nested scroll events for that nested scroll. 20105cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * </p> 20115cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 20125cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p><code>onNestedPreScroll</code> is called each time the nested scroll is updated 20135cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * by the nested scrolling child, before the nested scrolling child has consumed the scroll 20145cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * distance itself. <em>Each Behavior responding to the nested scroll will receive the 20155cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * same values.</em> The CoordinatorLayout will report as consumed the maximum number 20165cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * of pixels in either direction that any Behavior responding to the nested scroll reported 20175cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * as consumed.</p> 20185cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 20195cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is 20205cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * associated with 20215cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param child the child view of the CoordinatorLayout this Behavior is associated with 20225cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param target the descendant view of the CoordinatorLayout performing the nested scroll 20235cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param dx the raw horizontal number of pixels that the user attempted to scroll 20245cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param dy the raw vertical number of pixels that the user attempted to scroll 20255cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param consumed out parameter. consumed[0] should be set to the distance of dx that 20265cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * was consumed, consumed[1] should be set to the distance of dy that 20275cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * was consumed 20285cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 20295cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @see NestedScrollingParent#onNestedPreScroll(View, int, int, int[]) 20305cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell */ 20315cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, V child, View target, 20325cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell int dx, int dy, int[] consumed) { 20335cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell // Do nothing 20345cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 20355cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 20365cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell /** 20375cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * Called when a nested scrolling child is starting a fling or an action that would 20385cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * be a fling. 20395cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 20405cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p>Any Behavior associated with the direct child of the CoordinatorLayout may elect 20415cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * to accept the nested scroll as part of {@link #onStartNestedScroll}. Each Behavior 20425cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * that returned true will receive subsequent nested scroll events for that nested scroll. 20435cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * </p> 20445cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 20455cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p><code>onNestedFling</code> is called when the current nested scrolling child view 20465cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * detects the proper conditions for a fling. It reports if the child itself consumed 20475cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * the fling. If it did not, the child is expected to show some sort of overscroll 20485cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * indication. This method should return true if it consumes the fling, so that a child 20495cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * that did not itself take an action in response can choose not to show an overfling 20505cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * indication.</p> 20515cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 20525cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is 20535cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * associated with 20545cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param child the child view of the CoordinatorLayout this Behavior is associated with 20555cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param target the descendant view of the CoordinatorLayout performing the nested scroll 20565cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param velocityX horizontal velocity of the attempted fling 20575cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param velocityY vertical velocity of the attempted fling 20585cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param consumed true if the nested child view consumed the fling 20595cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @return true if the Behavior consumed the fling 20605cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 20615cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @see NestedScrollingParent#onNestedFling(View, float, float, boolean) 20625cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell */ 20635cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell public boolean onNestedFling(CoordinatorLayout coordinatorLayout, V child, View target, 20645cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell float velocityX, float velocityY, boolean consumed) { 20655cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell return false; 20665cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 20675cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 20685cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell /** 20695cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * Called when a nested scrolling child is about to start a fling. 20705cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 20715cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p>Any Behavior associated with the direct child of the CoordinatorLayout may elect 20725cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * to accept the nested scroll as part of {@link #onStartNestedScroll}. Each Behavior 20735cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * that returned true will receive subsequent nested scroll events for that nested scroll. 20745cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * </p> 20755cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 20765cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p><code>onNestedPreFling</code> is called when the current nested scrolling child view 20775cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * detects the proper conditions for a fling, but it has not acted on it yet. A 20785cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * Behavior can return true to indicate that it consumed the fling. If at least one 20795cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * Behavior returns true, the fling should not be acted upon by the child.</p> 20805cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 20815cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is 20825cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * associated with 20835cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param child the child view of the CoordinatorLayout this Behavior is associated with 20845cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param target the descendant view of the CoordinatorLayout performing the nested scroll 20855cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param velocityX horizontal velocity of the attempted fling 20865cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param velocityY vertical velocity of the attempted fling 20875cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @return true if the Behavior consumed the fling 20885cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 20895cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @see NestedScrollingParent#onNestedPreFling(View, float, float) 20905cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell */ 20915cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell public boolean onNestedPreFling(CoordinatorLayout coordinatorLayout, V child, View target, 20925cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell float velocityX, float velocityY) { 20935cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell return false; 20945cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 209575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 209675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes /** 209775284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * Called when the window insets have changed. 209875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * 209975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * <p>Any Behavior associated with the direct child of the CoordinatorLayout may elect 210075284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * to handle the window inset change on behalf of it's associated view. 210175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * </p> 210275284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * 210375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is 210475284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * associated with 210575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * @param child the child view of the CoordinatorLayout this Behavior is associated with 210675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * @param insets the new window insets. 210775284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * 210875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * @return The insets supplied, minus any insets that were consumed 210975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes */ 211075284fffafacd32f4d178020050589f9e70e5ed9Chris Banes public WindowInsetsCompat onApplyWindowInsets(CoordinatorLayout coordinatorLayout, 211175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes V child, WindowInsetsCompat insets) { 211275284fffafacd32f4d178020050589f9e70e5ed9Chris Banes return insets; 211375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 2114e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2115e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes /** 2116e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * Hook allowing a behavior to re-apply a representation of its internal state that had 2117e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * previously been generated by {@link #onSaveInstanceState}. This function will never 2118e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * be called with a null state. 2119e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * 2120e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * @param parent the parent CoordinatorLayout 2121e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * @param child child view to restore from 2122e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * @param state The frozen state that had previously been returned by 2123e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * {@link #onSaveInstanceState}. 2124e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * 2125e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * @see #onSaveInstanceState() 2126e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes */ 2127e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes public void onRestoreInstanceState(CoordinatorLayout parent, V child, Parcelable state) { 2128e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes // no-op 2129e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2130e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2131e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes /** 2132e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * Hook allowing a behavior to generate a representation of its internal state 2133e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * that can later be used to create a new instance with that same state. 2134e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * This state should only contain information that is not persistent or can 2135e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * not be reconstructed later. 2136e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * 2137e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * <p>Behavior state is only saved when both the parent {@link CoordinatorLayout} and 2138e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * a view using this behavior have valid IDs set.</p> 2139e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * 2140e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * @param parent the parent CoordinatorLayout 2141e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * @param child child view to restore from 2142e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * 2143e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * @return Returns a Parcelable object containing the behavior's current dynamic 2144e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * state. 2145e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * 2146e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * @see #onRestoreInstanceState(android.os.Parcelable) 2147e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * @see View#onSaveInstanceState() 2148e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes */ 2149e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes public Parcelable onSaveInstanceState(CoordinatorLayout parent, V child) { 2150e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes return BaseSavedState.EMPTY_STATE; 2151e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2152a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2153a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2154a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2155a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Parameters describing the desired layout for a child of a {@link CoordinatorLayout}. 2156a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2157a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public static class LayoutParams extends ViewGroup.MarginLayoutParams { 2158a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2159a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * A {@link Behavior} that the child view should obey. 2160a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2161a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Behavior mBehavior; 2162a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2163a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean mBehaviorResolved = false; 2164a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2165a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2166a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * A {@link Gravity} value describing how this child view should lay out. 2167a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * If an {@link #setAnchorId(int) anchor} is also specified, the gravity describes 2168a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * how this child view should be positioned relative to its anchored position. 2169a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2170a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public int gravity = Gravity.NO_GRAVITY; 2171a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2172a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2173a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * A {@link Gravity} value describing which edge of a child view's 2174a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link #getAnchorId() anchor} view the child should position itself relative to. 2175a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2176a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public int anchorGravity = Gravity.NO_GRAVITY; 2177a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2178a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2179a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * The index of the horizontal keyline specified to the parent CoordinatorLayout that this 2180a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * child should align relative to. If an {@link #setAnchorId(int) anchor} is present the 2181a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * keyline will be ignored. 2182a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2183a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public int keyline = -1; 2184a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2185a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2186a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * A {@link View#getId() view id} of a descendant view of the CoordinatorLayout that 2187a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * this child should position relative to. 2188a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2189a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int mAnchorId = View.NO_ID; 2190a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2191a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell View mAnchorView; 2192a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell View mAnchorDirectChild; 2193a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 21945cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell private boolean mDidBlockInteraction; 21955cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell private boolean mDidAcceptNestedScroll; 2196a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes private boolean mDidChangeAfterNestedScroll; 2197a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2198a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Rect mLastChildRect = new Rect(); 2199a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2200a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Object mBehaviorTag; 2201a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2202a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public LayoutParams(int width, int height) { 2203a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell super(width, height); 2204a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2205a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2206a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell LayoutParams(Context context, AttributeSet attrs) { 2207a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell super(context, attrs); 2208a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2209a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final TypedArray a = context.obtainStyledAttributes(attrs, 2210a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell R.styleable.CoordinatorLayout_LayoutParams); 2211a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2212a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell this.gravity = a.getInteger( 2213a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell R.styleable.CoordinatorLayout_LayoutParams_android_layout_gravity, 2214a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Gravity.NO_GRAVITY); 2215a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mAnchorId = a.getResourceId(R.styleable.CoordinatorLayout_LayoutParams_layout_anchor, 2216a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell View.NO_ID); 2217a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell this.anchorGravity = a.getInteger( 2218a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell R.styleable.CoordinatorLayout_LayoutParams_layout_anchorGravity, 2219a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Gravity.NO_GRAVITY); 2220a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2221a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell this.keyline = a.getInteger(R.styleable.CoordinatorLayout_LayoutParams_layout_keyline, 2222a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell -1); 2223a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2224a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mBehaviorResolved = a.hasValue( 2225a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell R.styleable.CoordinatorLayout_LayoutParams_layout_behavior); 2226a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mBehaviorResolved) { 2227a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mBehavior = parseBehavior(context, attrs, a.getString( 2228a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell R.styleable.CoordinatorLayout_LayoutParams_layout_behavior)); 2229a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2230a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2231a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell a.recycle(); 2232a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2233a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2234a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public LayoutParams(LayoutParams p) { 2235a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell super(p); 2236a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2237a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2238a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public LayoutParams(MarginLayoutParams p) { 2239a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell super(p); 2240a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2241a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2242a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public LayoutParams(ViewGroup.LayoutParams p) { 2243a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell super(p); 2244a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2245a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2246a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2247a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Get the id of this view's anchor. 2248a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2249a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>The view with this id must be a descendant of the CoordinatorLayout containing 2250a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * the child view this LayoutParams belongs to. It may not be the child view with 2251a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * this LayoutParams or a descendant of it.</p> 2252a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2253a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return A {@link View#getId() view id} or {@link View#NO_ID} if there is no anchor 2254a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2255a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public int getAnchorId() { 2256a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return mAnchorId; 2257a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2258a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2259a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2260a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Get the id of this view's anchor. 2261a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2262a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>The view with this id must be a descendant of the CoordinatorLayout containing 2263a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * the child view this LayoutParams belongs to. It may not be the child view with 2264a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * this LayoutParams or a descendant of it.</p> 2265a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2266a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param id The {@link View#getId() view id} of the anchor or 2267a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link View#NO_ID} if there is no anchor 2268a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2269a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public void setAnchorId(int id) { 2270a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell invalidateAnchor(); 2271a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mAnchorId = id; 2272a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2273a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2274a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2275a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Get the behavior governing the layout and interaction of the child view within 2276a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * a parent CoordinatorLayout. 2277a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2278a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return The current behavior or null if no behavior is specified 2279a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2280a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public Behavior getBehavior() { 2281a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return mBehavior; 2282a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2283a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2284a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2285a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Set the behavior governing the layout and interaction of the child view within 2286a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * a parent CoordinatorLayout. 2287a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2288a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>Setting a new behavior will remove any currently associated 2289a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link Behavior#setTag(android.view.View, Object) Behavior tag}.</p> 2290a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2291a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param behavior The behavior to set or null for no special behavior 2292a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2293a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public void setBehavior(Behavior behavior) { 2294a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mBehavior != behavior) { 2295a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mBehavior = behavior; 2296a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mBehaviorTag = null; 2297a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mBehaviorResolved = true; 2298a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2299a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2300a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2301a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2302a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Set the last known position rect for this child view 2303a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param r the rect to set 2304a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2305a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void setLastChildRect(Rect r) { 2306a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mLastChildRect.set(r); 2307a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2308a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2309a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2310a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Get the last known position rect for this child view. 2311a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Note: do not mutate the result of this call. 2312a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2313a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Rect getLastChildRect() { 2314a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return mLastChildRect; 2315a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2316a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2317a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2318a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Returns true if the anchor id changed to another valid view id since the anchor view 2319a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * was resolved. 2320a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2321a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean checkAnchorChanged() { 2322a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return mAnchorView == null && mAnchorId != View.NO_ID; 2323a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2324a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2325a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2326a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Returns true if the associated Behavior previously blocked interaction with other views 2327a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * below the associated child since the touch behavior tracking was last 2328a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link #resetTouchBehaviorTracking() reset}. 2329a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2330a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @see #isBlockingInteractionBelow(CoordinatorLayout, android.view.View) 2331a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2332a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean didBlockInteraction() { 2333a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mBehavior == null) { 2334a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mDidBlockInteraction = false; 2335a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2336a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return mDidBlockInteraction; 2337a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2338a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2339a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2340a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Check if the associated Behavior wants to block interaction below the given child 2341a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * view. The given child view should be the child this LayoutParams is associated with. 2342a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2343a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>Once interaction is blocked, it will remain blocked until touch interaction tracking 2344a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * is {@link #resetTouchBehaviorTracking() reset}.</p> 2345a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2346a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent CoordinatorLayout 2347a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child view this LayoutParams is associated with 2348a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true to block interaction below the given child 2349a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2350a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean isBlockingInteractionBelow(CoordinatorLayout parent, View child) { 2351a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mDidBlockInteraction) { 2352a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return true; 2353a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2354a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2355a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return mDidBlockInteraction |= mBehavior != null 2356a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell ? mBehavior.blocksInteractionBelow(parent, child) 2357a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell : false; 2358a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2359a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2360a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2361a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Reset tracking of Behavior-specific touch interactions. This includes 2362a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * interaction blocking. 2363a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2364a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @see #isBlockingInteractionBelow(CoordinatorLayout, android.view.View) 2365a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @see #didBlockInteraction() 2366a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2367a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void resetTouchBehaviorTracking() { 2368a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mDidBlockInteraction = false; 2369a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2370a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 23715cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell void resetNestedScroll() { 23725cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell mDidAcceptNestedScroll = false; 23735cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 23745cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 23755cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell void acceptNestedScroll(boolean accept) { 23765cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell mDidAcceptNestedScroll = accept; 23775cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 23785cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 23795cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell boolean isNestedScrollAccepted() { 23805cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell return mDidAcceptNestedScroll; 23815cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 23825cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 2383a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes boolean getChangedAfterNestedScroll() { 2384a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes return mDidChangeAfterNestedScroll; 2385a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 2386a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 2387a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes void setChangedAfterNestedScroll(boolean changed) { 2388a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes mDidChangeAfterNestedScroll = changed; 2389a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 2390a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 2391a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes void resetChangedAfterNestedScroll() { 2392a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes mDidChangeAfterNestedScroll = false; 2393a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 2394a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 2395a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2396a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Check if an associated child view depends on another child view of the CoordinatorLayout. 2397a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2398a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent CoordinatorLayout 2399a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child to check 2400a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param dependency the proposed dependency to check 2401a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true if child depends on dependency 2402a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2403a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean dependsOn(CoordinatorLayout parent, View child, View dependency) { 2404a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return dependency == mAnchorDirectChild 2405a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell || (mBehavior != null && mBehavior.layoutDependsOn(parent, child, dependency)); 2406a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2407a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2408a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2409a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Invalidate the cached anchor view and direct child ancestor of that anchor. 2410a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * The anchor will need to be 2411a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link #findAnchorView(CoordinatorLayout, android.view.View) found} before 2412a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * being used again. 2413a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2414a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void invalidateAnchor() { 2415a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mAnchorView = mAnchorDirectChild = null; 2416a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2417a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2418a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2419a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Locate the appropriate anchor view by the current {@link #setAnchorId(int) anchor id} 2420a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * or return the cached anchor view if already known. 2421a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2422a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent CoordinatorLayout 2423a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param forChild the child this LayoutParams is associated with 2424a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return the located descendant anchor view, or null if the anchor id is 2425a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link View#NO_ID}. 2426a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2427a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell View findAnchorView(CoordinatorLayout parent, View forChild) { 2428a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mAnchorId == View.NO_ID) { 2429a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mAnchorView = mAnchorDirectChild = null; 2430a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return null; 2431a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2432a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2433a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mAnchorView == null || !verifyAnchorView(forChild, parent)) { 2434a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell resolveAnchorView(forChild, parent); 2435a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2436a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return mAnchorView; 2437a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2438a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2439a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2440a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Check if the child associated with this LayoutParams is currently considered 2441a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * "dirty" and needs to be updated. A Behavior should consider a child dirty 2442a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * whenever a property returned by another Behavior method would have changed, 2443a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * such as dependencies. 2444a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2445a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent CoordinatorLayout 2446a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child view associated with this LayoutParams 2447a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true if this child view should be considered dirty 2448a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2449a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean isDirty(CoordinatorLayout parent, View child) { 2450a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return mBehavior != null && mBehavior.isDirty(parent, child); 2451a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2452a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2453a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2454a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Determine the anchor view for the child view this LayoutParams is assigned to. 2455a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Assumes mAnchorId is valid. 2456a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2457a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private void resolveAnchorView(View forChild, CoordinatorLayout parent) { 2458a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mAnchorView = parent.findViewById(mAnchorId); 2459a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mAnchorView != null) { 2460a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell View directChild = mAnchorView; 2461a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (ViewParent p = mAnchorView.getParent(); 2462a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell p != parent && p != null; 2463a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell p = p.getParent()) { 2464a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (p == forChild) { 2465a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (parent.isInEditMode()) { 2466a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mAnchorView = mAnchorDirectChild = null; 2467a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return; 2468a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2469a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell throw new IllegalStateException( 2470a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell "Anchor must not be a descendant of the anchored view"); 2471a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2472a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (p instanceof View) { 2473a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell directChild = (View) p; 2474a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2475a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2476a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mAnchorDirectChild = directChild; 2477a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else { 2478a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (parent.isInEditMode()) { 2479a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mAnchorView = mAnchorDirectChild = null; 2480a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return; 2481a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2482a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell throw new IllegalStateException("Could not find CoordinatorLayout descendant view" 2483a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell + " with id " + parent.getResources().getResourceName(mAnchorId) 2484a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell + " to anchor view " + forChild); 2485a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2486a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2487a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2488a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2489a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Verify that the previously resolved anchor view is still valid - that it is still 2490a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * a descendant of the expected parent view, it is not the child this LayoutParams 2491a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * is assigned to or a descendant of it, and it has the expected id. 2492a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2493a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private boolean verifyAnchorView(View forChild, CoordinatorLayout parent) { 2494a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mAnchorView.getId() != mAnchorId) { 2495a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return false; 2496a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2497a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2498a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell View directChild = mAnchorView; 2499a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (ViewParent p = mAnchorView.getParent(); 2500a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell p != parent; 2501a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell p = p.getParent()) { 2502a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (p == null || p == forChild) { 2503a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mAnchorView = mAnchorDirectChild = null; 2504a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return false; 2505a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2506a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (p instanceof View) { 2507a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell directChild = (View) p; 2508a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2509a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2510a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mAnchorDirectChild = directChild; 2511a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return true; 2512a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2513a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 251475284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 251575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes final class ApplyInsetsListener implements android.support.v4.view.OnApplyWindowInsetsListener { 251675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes @Override 251775284fffafacd32f4d178020050589f9e70e5ed9Chris Banes public WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat insets) { 251875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes setWindowInsets(insets); 251975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes return insets.consumeSystemWindowInsets(); 252075284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 252175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 2522e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 25230b00489086b22c9688c8c04990dadf54489d45e3Chris Banes final class HierarchyChangeListener implements OnHierarchyChangeListener { 25240b00489086b22c9688c8c04990dadf54489d45e3Chris Banes @Override 25250b00489086b22c9688c8c04990dadf54489d45e3Chris Banes public void onChildViewAdded(View parent, View child) { 25260b00489086b22c9688c8c04990dadf54489d45e3Chris Banes if (mOnHierarchyChangeListener != null) { 25270b00489086b22c9688c8c04990dadf54489d45e3Chris Banes mOnHierarchyChangeListener.onChildViewAdded(parent, child); 25280b00489086b22c9688c8c04990dadf54489d45e3Chris Banes } 25290b00489086b22c9688c8c04990dadf54489d45e3Chris Banes } 25300b00489086b22c9688c8c04990dadf54489d45e3Chris Banes 25310b00489086b22c9688c8c04990dadf54489d45e3Chris Banes @Override 25320b00489086b22c9688c8c04990dadf54489d45e3Chris Banes public void onChildViewRemoved(View parent, View child) { 25330b00489086b22c9688c8c04990dadf54489d45e3Chris Banes dispatchDependentViewRemoved(child); 25340b00489086b22c9688c8c04990dadf54489d45e3Chris Banes 25350b00489086b22c9688c8c04990dadf54489d45e3Chris Banes if (mOnHierarchyChangeListener != null) { 25360b00489086b22c9688c8c04990dadf54489d45e3Chris Banes mOnHierarchyChangeListener.onChildViewRemoved(parent, child); 25370b00489086b22c9688c8c04990dadf54489d45e3Chris Banes } 25380b00489086b22c9688c8c04990dadf54489d45e3Chris Banes } 25390b00489086b22c9688c8c04990dadf54489d45e3Chris Banes } 25400b00489086b22c9688c8c04990dadf54489d45e3Chris Banes 2541e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes @Override 2542e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes protected void onRestoreInstanceState(Parcelable state) { 2543e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final SavedState ss = (SavedState) state; 2544e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes super.onRestoreInstanceState(ss.getSuperState()); 2545e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2546e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final SparseArray<Parcelable> behaviorStates = ss.behaviorStates; 2547e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2548e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes for (int i = 0, count = getChildCount(); i < count; i++) { 2549e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final View child = getChildAt(i); 2550e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final int childId = child.getId(); 2551e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final LayoutParams lp = getResolvedLayoutParams(child); 2552e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final Behavior b = lp.getBehavior(); 2553e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2554e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes if (childId != NO_ID && b != null) { 2555e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes Parcelable savedState = behaviorStates.get(childId); 2556e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes if (savedState != null) { 2557e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes b.onRestoreInstanceState(this, child, savedState); 2558e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2559e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2560e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2561e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2562e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2563e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes @Override 2564e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes protected Parcelable onSaveInstanceState() { 2565e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final SavedState ss = new SavedState(super.onSaveInstanceState()); 2566e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2567e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final SparseArray<Parcelable> behaviorStates = new SparseArray<>(); 2568e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes for (int i = 0, count = getChildCount(); i < count; i++) { 2569e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final View child = getChildAt(i); 2570e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final int childId = child.getId(); 2571e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 2572e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final Behavior b = lp.getBehavior(); 2573e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2574e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes if (childId != NO_ID && b != null) { 2575e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes // If the child has an ID and a Behavior, let it save some state... 2576e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes Parcelable state = b.onSaveInstanceState(this, child); 2577e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes if (state != null) { 2578e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes behaviorStates.append(childId, state); 2579e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2580e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2581e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2582e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes ss.behaviorStates = behaviorStates; 2583e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes return ss; 2584e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2585e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2586e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes protected static class SavedState extends BaseSavedState { 2587e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes SparseArray<Parcelable> behaviorStates; 2588e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2589e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes public SavedState(Parcel source) { 2590e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes super(source); 2591e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2592e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final int size = source.readInt(); 2593e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2594e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final int[] ids = new int[size]; 2595e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes source.readIntArray(ids); 2596e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2597e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final Parcelable[] states = source.readParcelableArray( 2598e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes CoordinatorLayout.class.getClassLoader()); 2599e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2600e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes behaviorStates = new SparseArray<>(size); 2601e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes for (int i = 0; i < size; i++) { 2602e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes behaviorStates.append(ids[i], states[i]); 2603e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2604e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2605e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2606e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes public SavedState(Parcelable superState) { 2607e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes super(superState); 2608e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2609e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2610e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes @Override 2611e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes public void writeToParcel(Parcel dest, int flags) { 2612e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes super.writeToParcel(dest, flags); 2613e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2614e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final int size = behaviorStates != null ? behaviorStates.size() : 0; 2615e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes dest.writeInt(size); 2616e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2617e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final int[] ids = new int[size]; 2618e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final Parcelable[] states = new Parcelable[size]; 2619e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2620e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes for (int i = 0; i < size; i++) { 2621e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes ids[i] = behaviorStates.keyAt(i); 2622e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes states[i] = behaviorStates.valueAt(i); 2623e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2624e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes dest.writeIntArray(ids); 2625e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes dest.writeParcelableArray(states, flags); 2626e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2627e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2628e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2629e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes public static final Parcelable.Creator<SavedState> CREATOR = 2630e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes new Parcelable.Creator<SavedState>() { 2631e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes @Override 2632e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes public SavedState createFromParcel(Parcel source) { 2633e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes return new SavedState(source); 2634e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2635e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2636e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes @Override 2637e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes public SavedState[] newArray(int size) { 2638e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes return new SavedState[size]; 2639e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2640e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes }; 2641e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2642a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell} 2643