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; 26b806673aa0977685995be820981207f6bf51858bChris Banesimport android.graphics.Region; 2775284fffafacd32f4d178020050589f9e70e5ed9Chris Banesimport android.graphics.drawable.ColorDrawable; 2875284fffafacd32f4d178020050589f9e70e5ed9Chris Banesimport android.graphics.drawable.Drawable; 29a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.os.Build; 30e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banesimport android.os.Parcel; 31e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banesimport android.os.Parcelable; 32a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.os.SystemClock; 33bcb330de0c625b371010bada2a51363fc37b52ccChris Banesimport android.support.annotation.ColorInt; 34bcb330de0c625b371010bada2a51363fc37b52ccChris Banesimport android.support.annotation.DrawableRes; 35b806673aa0977685995be820981207f6bf51858bChris Banesimport android.support.annotation.FloatRange; 3626c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banesimport android.support.annotation.IdRes; 3726c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banesimport android.support.annotation.IntDef; 383035e10317eb12c58153d8c651a791896ea3094eChris Banesimport android.support.annotation.NonNull; 39bcb330de0c625b371010bada2a51363fc37b52ccChris Banesimport android.support.annotation.Nullable; 40c39d9c75590eca86a5e7e32a8824ba04a0d42e9bAlan Viveretteimport android.support.annotation.RestrictTo; 41a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banesimport android.support.annotation.VisibleForTesting; 42a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.support.design.R; 4375284fffafacd32f4d178020050589f9e70e5ed9Chris Banesimport android.support.v4.content.ContextCompat; 44bcb330de0c625b371010bada2a51363fc37b52ccChris Banesimport android.support.v4.graphics.drawable.DrawableCompat; 4562ab25d71ccfa775a8bd2add7b41277bc4e14bbcChris Banesimport android.support.v4.os.ParcelableCompat; 4662ab25d71ccfa775a8bd2add7b41277bc4e14bbcChris Banesimport android.support.v4.os.ParcelableCompatCreatorCallbacks; 4705f5ba020fa6caa658c75b6d77436aa980ca0fccChris Banesimport android.support.v4.view.AbsSavedState; 48a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.support.v4.view.GravityCompat; 4988cccf6c76b6a1c2d67152c2de5599f3c8301b18Chris Banesimport android.support.v4.view.MotionEventCompat; 50a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.support.v4.view.NestedScrollingParent; 51a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.support.v4.view.NestedScrollingParentHelper; 52a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.support.v4.view.ViewCompat; 5375284fffafacd32f4d178020050589f9e70e5ed9Chris Banesimport android.support.v4.view.WindowInsetsCompat; 54a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.text.TextUtils; 55a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.util.AttributeSet; 56a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.util.Log; 57e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banesimport android.util.SparseArray; 58a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.view.Gravity; 59a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.view.MotionEvent; 60a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.view.View; 61a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.view.ViewGroup; 62a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.view.ViewParent; 63a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.view.ViewTreeObserver; 64a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 65a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport java.lang.annotation.Retention; 66a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport java.lang.annotation.RetentionPolicy; 67a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport java.lang.reflect.Constructor; 68a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport java.util.ArrayList; 69a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport java.util.Collections; 70a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport java.util.Comparator; 71a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport java.util.HashMap; 72a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport java.util.List; 73a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport java.util.Map; 74a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 75c39d9c75590eca86a5e7e32a8824ba04a0d42e9bAlan Viveretteimport static android.support.annotation.RestrictTo.Scope.GROUP_ID; 7619a80415a88ecfae6bbc645cd14b653ed4337648Chris Banesimport static android.support.design.widget.ViewUtils.objectEquals; 7719a80415a88ecfae6bbc645cd14b653ed4337648Chris Banes 78a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell/** 79a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * CoordinatorLayout is a super-powered {@link android.widget.FrameLayout FrameLayout}. 80a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 81a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>CoordinatorLayout is intended for two primary use cases:</p> 82a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <ol> 83a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <li>As a top-level application decor or chrome layout</li> 84a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <li>As a container for a specific interaction with one or more child views</li> 85a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * </ol> 86a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 87a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>By specifying {@link CoordinatorLayout.Behavior Behaviors} for child views of a 88a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * CoordinatorLayout you can provide many different interactions within a single parent and those 89a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * views can also interact with one another. View classes can specify a default behavior when 90a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * used as a child of a CoordinatorLayout using the 91a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link CoordinatorLayout.DefaultBehavior DefaultBehavior} annotation.</p> 92a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 93a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>Behaviors may be used to implement a variety of interactions and additional layout 94a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * modifications ranging from sliding drawers and panels to swipe-dismissable elements and buttons 95a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * that stick to other elements as they move and animate.</p> 96a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 97a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>Children of a CoordinatorLayout may have an 98a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link CoordinatorLayout.LayoutParams#setAnchorId(int) anchor}. This view id must correspond 99a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * to an arbitrary descendant of the CoordinatorLayout, but it may not be the anchored child itself 100a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * or a descendant of the anchored child. This can be used to place floating views relative to 101a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * other arbitrary content panes.</p> 1021ca24096efc933932416645c546dbd9ac91efbebYuichi Araki * 1031ca24096efc933932416645c546dbd9ac91efbebYuichi Araki * <p>Children can specify {@link CoordinatorLayout.LayoutParams#insetEdge} to describe how the 1041ca24096efc933932416645c546dbd9ac91efbebYuichi Araki * view insets the CoordinatorLayout. Any child views which are set to dodge the same inset edges by 1051ca24096efc933932416645c546dbd9ac91efbebYuichi Araki * {@link CoordinatorLayout.LayoutParams#dodgeInsetEdges} will be moved appropriately so that the 1061ca24096efc933932416645c546dbd9ac91efbebYuichi Araki * views do not overlap.</p> 107a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 108a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellpublic class CoordinatorLayout extends ViewGroup implements NestedScrollingParent { 109a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell static final String TAG = "CoordinatorLayout"; 11025ef4026b72ff670ee07c81897124732d3f5f443Chris Banes static final String WIDGET_PACKAGE_NAME; 11125ef4026b72ff670ee07c81897124732d3f5f443Chris Banes 11225ef4026b72ff670ee07c81897124732d3f5f443Chris Banes static { 11325ef4026b72ff670ee07c81897124732d3f5f443Chris Banes final Package pkg = CoordinatorLayout.class.getPackage(); 11425ef4026b72ff670ee07c81897124732d3f5f443Chris Banes WIDGET_PACKAGE_NAME = pkg != null ? pkg.getName() : null; 11525ef4026b72ff670ee07c81897124732d3f5f443Chris Banes } 116a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 117d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes private static final int TYPE_ON_INTERCEPT = 0; 118d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes private static final int TYPE_ON_TOUCH = 1; 119d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes 120a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell static { 121a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes if (Build.VERSION.SDK_INT >= 21) { 122a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell TOP_SORTED_CHILDREN_COMPARATOR = new ViewElevationComparator(); 123a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else { 124a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell TOP_SORTED_CHILDREN_COMPARATOR = null; 125a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 126a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 127a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 128a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell static final Class<?>[] CONSTRUCTOR_PARAMS = new Class<?>[] { 129a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Context.class, 130a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell AttributeSet.class 131a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell }; 132a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 133a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell static final ThreadLocal<Map<String, Constructor<Behavior>>> sConstructors = 134a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell new ThreadLocal<>(); 135a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 136a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 137657ea1100fee4750f148f9d0dcb7e7e2028f105eAurimas Liutikas static final int EVENT_PRE_DRAW = 0; 138657ea1100fee4750f148f9d0dcb7e7e2028f105eAurimas Liutikas static final int EVENT_NESTED_SCROLL = 1; 139657ea1100fee4750f148f9d0dcb7e7e2028f105eAurimas Liutikas static final int EVENT_VIEW_REMOVED = 2; 14026c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes 14126c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes /** @hide */ 142c39d9c75590eca86a5e7e32a8824ba04a0d42e9bAlan Viverette @RestrictTo(GROUP_ID) 14326c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes @Retention(RetentionPolicy.SOURCE) 14426c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes @IntDef({EVENT_PRE_DRAW, EVENT_NESTED_SCROLL, EVENT_VIEW_REMOVED}) 14526c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes public @interface DispatchChangeEvent {} 14626c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes 147a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell static final Comparator<View> TOP_SORTED_CHILDREN_COMPARATOR; 148a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 149a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes private final List<View> mDependencySortedChildren = new ArrayList<>(); 150a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes private final DirectedAcyclicGraph<View> mChildDag = new DirectedAcyclicGraph<>(); 151a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes 152a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes private final List<View> mTempList1 = new ArrayList<>(); 153a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes private final List<View> mTempDependenciesList = new ArrayList<>(); 154a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private final Rect mTempRect1 = new Rect(); 155a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private final Rect mTempRect2 = new Rect(); 156a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private final Rect mTempRect3 = new Rect(); 157943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki private final Rect mTempRect4 = new Rect(); 1585cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell private final int[] mTempIntPair = new int[2]; 159a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private Paint mScrimPaint; 160a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 16178d6f4ad1fc1e2d57b138e31f47f2267731ee95eAurimas Liutikas private boolean mDisallowInterceptReset; 16278d6f4ad1fc1e2d57b138e31f47f2267731ee95eAurimas Liutikas 163a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private boolean mIsAttachedToWindow; 164a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 165a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private int[] mKeylines; 166a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 167a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private View mBehaviorTouchView; 1685cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell private View mNestedScrollingDirectChild; 1695cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell private View mNestedScrollingTarget; 170a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 171a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private OnPreDrawListener mOnPreDrawListener; 172a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private boolean mNeedsPreDrawListener; 173a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 17475284fffafacd32f4d178020050589f9e70e5ed9Chris Banes private WindowInsetsCompat mLastInsets; 17575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes private boolean mDrawStatusBarBackground; 17675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes private Drawable mStatusBarBackground; 17775284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 178657ea1100fee4750f148f9d0dcb7e7e2028f105eAurimas Liutikas OnHierarchyChangeListener mOnHierarchyChangeListener; 1793035e10317eb12c58153d8c651a791896ea3094eChris Banes private android.support.v4.view.OnApplyWindowInsetsListener mApplyWindowInsetsListener; 1800b00489086b22c9688c8c04990dadf54489d45e3Chris Banes 181a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private final NestedScrollingParentHelper mNestedScrollingParentHelper = 182a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell new NestedScrollingParentHelper(this); 183a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 184a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public CoordinatorLayout(Context context) { 185a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell this(context, null); 186a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 187a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 188a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public CoordinatorLayout(Context context, AttributeSet attrs) { 189a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell this(context, attrs, 0); 190a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 191a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 192a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public CoordinatorLayout(Context context, AttributeSet attrs, int defStyleAttr) { 193a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell super(context, attrs, defStyleAttr); 194a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 195809bb62055ad42b88f3a69308be222801b89fbd9Chris Banes ThemeUtils.checkAppCompatTheme(context); 196809bb62055ad42b88f3a69308be222801b89fbd9Chris Banes 197a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CoordinatorLayout, 19875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes defStyleAttr, R.style.Widget_Design_CoordinatorLayout); 199a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int keylineArrayRes = a.getResourceId(R.styleable.CoordinatorLayout_keylines, 0); 200a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (keylineArrayRes != 0) { 201a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Resources res = context.getResources(); 202a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mKeylines = res.getIntArray(keylineArrayRes); 203a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final float density = res.getDisplayMetrics().density; 204a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int count = mKeylines.length; 205a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int i = 0; i < count; i++) { 206a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mKeylines[i] *= density; 207a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 208a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 20975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes mStatusBarBackground = a.getDrawable(R.styleable.CoordinatorLayout_statusBarBackground); 210a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell a.recycle(); 21175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 2123035e10317eb12c58153d8c651a791896ea3094eChris Banes setupForInsets(); 2130b00489086b22c9688c8c04990dadf54489d45e3Chris Banes super.setOnHierarchyChangeListener(new HierarchyChangeListener()); 2140b00489086b22c9688c8c04990dadf54489d45e3Chris Banes } 2150b00489086b22c9688c8c04990dadf54489d45e3Chris Banes 2160b00489086b22c9688c8c04990dadf54489d45e3Chris Banes @Override 2170b00489086b22c9688c8c04990dadf54489d45e3Chris Banes public void setOnHierarchyChangeListener(OnHierarchyChangeListener onHierarchyChangeListener) { 2180b00489086b22c9688c8c04990dadf54489d45e3Chris Banes mOnHierarchyChangeListener = onHierarchyChangeListener; 219a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 220a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 221a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 222a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public void onAttachedToWindow() { 223a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell super.onAttachedToWindow(); 2245cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell resetTouchBehaviors(); 225a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mNeedsPreDrawListener) { 226a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mOnPreDrawListener == null) { 227a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mOnPreDrawListener = new OnPreDrawListener(); 228a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 229a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final ViewTreeObserver vto = getViewTreeObserver(); 230a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell vto.addOnPreDrawListener(mOnPreDrawListener); 231a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 232e3f6ba486fec4e11ca7508049ac81de4c7102f23Chris Banes if (mLastInsets == null && ViewCompat.getFitsSystemWindows(this)) { 233e3f6ba486fec4e11ca7508049ac81de4c7102f23Chris Banes // We're set to fitSystemWindows but we haven't had any insets yet... 234e3f6ba486fec4e11ca7508049ac81de4c7102f23Chris Banes // We should request a new dispatch of window insets 235e3f6ba486fec4e11ca7508049ac81de4c7102f23Chris Banes ViewCompat.requestApplyInsets(this); 236e3f6ba486fec4e11ca7508049ac81de4c7102f23Chris Banes } 237a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mIsAttachedToWindow = true; 238a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 239a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 240a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 241a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public void onDetachedFromWindow() { 242a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell super.onDetachedFromWindow(); 2435cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell resetTouchBehaviors(); 244a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mNeedsPreDrawListener && mOnPreDrawListener != null) { 245a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final ViewTreeObserver vto = getViewTreeObserver(); 246a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell vto.removeOnPreDrawListener(mOnPreDrawListener); 247a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2485cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (mNestedScrollingTarget != null) { 2495cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell onStopNestedScroll(mNestedScrollingTarget); 2505cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 251a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mIsAttachedToWindow = false; 252a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 253a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 254a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 25575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * Set a drawable to draw in the insets area for the status bar. 25675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * Note that this will only be activated if this DrawerLayout fitsSystemWindows. 25775284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * 25875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * @param bg Background drawable to draw behind the status bar 25975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes */ 260bcb330de0c625b371010bada2a51363fc37b52ccChris Banes public void setStatusBarBackground(@Nullable final Drawable bg) { 261bcb330de0c625b371010bada2a51363fc37b52ccChris Banes if (mStatusBarBackground != bg) { 262bcb330de0c625b371010bada2a51363fc37b52ccChris Banes if (mStatusBarBackground != null) { 263bcb330de0c625b371010bada2a51363fc37b52ccChris Banes mStatusBarBackground.setCallback(null); 264bcb330de0c625b371010bada2a51363fc37b52ccChris Banes } 265bcb330de0c625b371010bada2a51363fc37b52ccChris Banes mStatusBarBackground = bg != null ? bg.mutate() : null; 266bcb330de0c625b371010bada2a51363fc37b52ccChris Banes if (mStatusBarBackground != null) { 267bcb330de0c625b371010bada2a51363fc37b52ccChris Banes if (mStatusBarBackground.isStateful()) { 268bcb330de0c625b371010bada2a51363fc37b52ccChris Banes mStatusBarBackground.setState(getDrawableState()); 269bcb330de0c625b371010bada2a51363fc37b52ccChris Banes } 270bcb330de0c625b371010bada2a51363fc37b52ccChris Banes DrawableCompat.setLayoutDirection(mStatusBarBackground, 271bcb330de0c625b371010bada2a51363fc37b52ccChris Banes ViewCompat.getLayoutDirection(this)); 272bcb330de0c625b371010bada2a51363fc37b52ccChris Banes mStatusBarBackground.setVisible(getVisibility() == VISIBLE, false); 273bcb330de0c625b371010bada2a51363fc37b52ccChris Banes mStatusBarBackground.setCallback(this); 274bcb330de0c625b371010bada2a51363fc37b52ccChris Banes } 275bcb330de0c625b371010bada2a51363fc37b52ccChris Banes ViewCompat.postInvalidateOnAnimation(this); 276bcb330de0c625b371010bada2a51363fc37b52ccChris Banes } 27775284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 27875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 27975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes /** 28075284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * Gets the drawable used to draw in the insets area for the status bar. 28175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * 28275284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * @return The status bar background drawable, or null if none set 28375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes */ 284bcb330de0c625b371010bada2a51363fc37b52ccChris Banes @Nullable 28575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes public Drawable getStatusBarBackground() { 28675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes return mStatusBarBackground; 28775284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 28875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 289bcb330de0c625b371010bada2a51363fc37b52ccChris Banes @Override 290bcb330de0c625b371010bada2a51363fc37b52ccChris Banes protected void drawableStateChanged() { 291bcb330de0c625b371010bada2a51363fc37b52ccChris Banes super.drawableStateChanged(); 292bcb330de0c625b371010bada2a51363fc37b52ccChris Banes 293bcb330de0c625b371010bada2a51363fc37b52ccChris Banes final int[] state = getDrawableState(); 294bcb330de0c625b371010bada2a51363fc37b52ccChris Banes boolean changed = false; 295bcb330de0c625b371010bada2a51363fc37b52ccChris Banes 296bcb330de0c625b371010bada2a51363fc37b52ccChris Banes Drawable d = mStatusBarBackground; 297bcb330de0c625b371010bada2a51363fc37b52ccChris Banes if (d != null && d.isStateful()) { 298bcb330de0c625b371010bada2a51363fc37b52ccChris Banes changed |= d.setState(state); 299bcb330de0c625b371010bada2a51363fc37b52ccChris Banes } 300bcb330de0c625b371010bada2a51363fc37b52ccChris Banes 301bcb330de0c625b371010bada2a51363fc37b52ccChris Banes if (changed) { 302bcb330de0c625b371010bada2a51363fc37b52ccChris Banes invalidate(); 303bcb330de0c625b371010bada2a51363fc37b52ccChris Banes } 304bcb330de0c625b371010bada2a51363fc37b52ccChris Banes } 305bcb330de0c625b371010bada2a51363fc37b52ccChris Banes 306bcb330de0c625b371010bada2a51363fc37b52ccChris Banes @Override 307bcb330de0c625b371010bada2a51363fc37b52ccChris Banes protected boolean verifyDrawable(Drawable who) { 308bcb330de0c625b371010bada2a51363fc37b52ccChris Banes return super.verifyDrawable(who) || who == mStatusBarBackground; 309bcb330de0c625b371010bada2a51363fc37b52ccChris Banes } 310bcb330de0c625b371010bada2a51363fc37b52ccChris Banes 311bcb330de0c625b371010bada2a51363fc37b52ccChris Banes @Override 312bcb330de0c625b371010bada2a51363fc37b52ccChris Banes public void setVisibility(int visibility) { 313bcb330de0c625b371010bada2a51363fc37b52ccChris Banes super.setVisibility(visibility); 314bcb330de0c625b371010bada2a51363fc37b52ccChris Banes 315bcb330de0c625b371010bada2a51363fc37b52ccChris Banes final boolean visible = visibility == VISIBLE; 316bcb330de0c625b371010bada2a51363fc37b52ccChris Banes if (mStatusBarBackground != null && mStatusBarBackground.isVisible() != visible) { 317bcb330de0c625b371010bada2a51363fc37b52ccChris Banes mStatusBarBackground.setVisible(visible, false); 318bcb330de0c625b371010bada2a51363fc37b52ccChris Banes } 319bcb330de0c625b371010bada2a51363fc37b52ccChris Banes } 320bcb330de0c625b371010bada2a51363fc37b52ccChris Banes 32175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes /** 32275284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * Set a drawable to draw in the insets area for the status bar. 32375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * Note that this will only be activated if this DrawerLayout fitsSystemWindows. 32475284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * 32575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * @param resId Resource id of a background drawable to draw behind the status bar 32675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes */ 327bcb330de0c625b371010bada2a51363fc37b52ccChris Banes public void setStatusBarBackgroundResource(@DrawableRes int resId) { 32875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes setStatusBarBackground(resId != 0 ? ContextCompat.getDrawable(getContext(), resId) : null); 32975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 33075284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 33175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes /** 33275284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * Set a drawable to draw in the insets area for the status bar. 33375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * Note that this will only be activated if this DrawerLayout fitsSystemWindows. 33475284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * 33575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * @param color Color to use as a background drawable to draw behind the status bar 33675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * in 0xAARRGGBB format. 33775284fffafacd32f4d178020050589f9e70e5ed9Chris Banes */ 338bcb330de0c625b371010bada2a51363fc37b52ccChris Banes public void setStatusBarBackgroundColor(@ColorInt int color) { 33975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes setStatusBarBackground(new ColorDrawable(color)); 34075284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 34175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 3423035e10317eb12c58153d8c651a791896ea3094eChris Banes final WindowInsetsCompat setWindowInsets(WindowInsetsCompat insets) { 34319a80415a88ecfae6bbc645cd14b653ed4337648Chris Banes if (!objectEquals(mLastInsets, insets)) { 34475284fffafacd32f4d178020050589f9e70e5ed9Chris Banes mLastInsets = insets; 34575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes mDrawStatusBarBackground = insets != null && insets.getSystemWindowInsetTop() > 0; 34675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes setWillNotDraw(!mDrawStatusBarBackground && getBackground() == null); 34717ed3263761329f6aa6796941358c41001fff325Chris Banes 34817ed3263761329f6aa6796941358c41001fff325Chris Banes // Now dispatch to the Behaviors 34917ed3263761329f6aa6796941358c41001fff325Chris Banes insets = dispatchApplyWindowInsetsToBehaviors(insets); 35075284fffafacd32f4d178020050589f9e70e5ed9Chris Banes requestLayout(); 35175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 35217ed3263761329f6aa6796941358c41001fff325Chris Banes return insets; 35375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 35475284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 3552e522d2998c937948757ccfe0a5523047726fb4dChris Banes final WindowInsetsCompat getLastWindowInsets() { 3562e522d2998c937948757ccfe0a5523047726fb4dChris Banes return mLastInsets; 3572e522d2998c937948757ccfe0a5523047726fb4dChris Banes } 3582e522d2998c937948757ccfe0a5523047726fb4dChris Banes 35975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes /** 360a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Reset all Behavior-related tracking records either to clean up or in preparation 361a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * for a new event stream. This should be called when attached or detached from a window, 362a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * in response to an UP or CANCEL event, when intercept is request-disallowed 363a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * and similar cases where an event stream in progress will be aborted. 364a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 3655cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell private void resetTouchBehaviors() { 366a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mBehaviorTouchView != null) { 367a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Behavior b = ((LayoutParams) mBehaviorTouchView.getLayoutParams()).getBehavior(); 368a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (b != null) { 369a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final long now = SystemClock.uptimeMillis(); 370a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final MotionEvent cancelEvent = MotionEvent.obtain(now, now, 371a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0); 372a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell b.onTouchEvent(this, mBehaviorTouchView, cancelEvent); 373a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell cancelEvent.recycle(); 374a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 375a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mBehaviorTouchView = null; 376a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 377a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 378a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childCount = getChildCount(); 379a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int i = 0; i < childCount; i++) { 380a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final View child = getChildAt(i); 381a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 382a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell lp.resetTouchBehaviorTracking(); 383a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 38478d6f4ad1fc1e2d57b138e31f47f2267731ee95eAurimas Liutikas mDisallowInterceptReset = false; 385a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 386a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 387a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 388a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Populate a list with the current child views, sorted such that the topmost views 389a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * in z-order are at the front of the list. Useful for hit testing and event dispatch. 390a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 391a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private void getTopSortedChildren(List<View> out) { 392a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell out.clear(); 393a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 394a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final boolean useCustomOrder = isChildrenDrawingOrderEnabled(); 395a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childCount = getChildCount(); 396a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int i = childCount - 1; i >= 0; i--) { 397a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childIndex = useCustomOrder ? getChildDrawingOrder(childCount, i) : i; 398a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final View child = getChildAt(childIndex); 399a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell out.add(child); 400a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 401a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 402a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (TOP_SORTED_CHILDREN_COMPARATOR != null) { 403a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Collections.sort(out, TOP_SORTED_CHILDREN_COMPARATOR); 404a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 405a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 406a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 407d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes private boolean performIntercept(MotionEvent ev, final int type) { 408a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean intercepted = false; 409a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean newBlock = false; 410a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 411a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell MotionEvent cancelEvent = null; 412a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 41388cccf6c76b6a1c2d67152c2de5599f3c8301b18Chris Banes final int action = MotionEventCompat.getActionMasked(ev); 414a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 415a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes final List<View> topmostChildList = mTempList1; 416a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getTopSortedChildren(topmostChildList); 417a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 418a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Let topmost child views inspect first 419a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childCount = topmostChildList.size(); 420a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int i = 0; i < childCount; i++) { 421a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final View child = topmostChildList.get(i); 422a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 423a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Behavior b = lp.getBehavior(); 424a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 425a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if ((intercepted || newBlock) && action != MotionEvent.ACTION_DOWN) { 426a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Cancel all behaviors beneath the one that intercepted. 427a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // If the event is "down" then we don't have anything to cancel yet. 428a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (b != null) { 429515613db9b9d82472c8fce69b2b104c277f68b99Chris Banes if (cancelEvent == null) { 430a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final long now = SystemClock.uptimeMillis(); 431a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell cancelEvent = MotionEvent.obtain(now, now, 432a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0); 433a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 434d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes switch (type) { 435d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes case TYPE_ON_INTERCEPT: 436d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes b.onInterceptTouchEvent(this, child, cancelEvent); 437d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes break; 438d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes case TYPE_ON_TOUCH: 439d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes b.onTouchEvent(this, child, cancelEvent); 440d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes break; 441d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes } 442a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 443a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell continue; 444a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 445a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 446d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes if (!intercepted && b != null) { 447d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes switch (type) { 448d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes case TYPE_ON_INTERCEPT: 449d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes intercepted = b.onInterceptTouchEvent(this, child, ev); 450d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes break; 451d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes case TYPE_ON_TOUCH: 452d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes intercepted = b.onTouchEvent(this, child, ev); 453d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes break; 454d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes } 455d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes if (intercepted) { 456d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes mBehaviorTouchView = child; 457d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes } 458a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 459a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 460a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Don't keep going if we're not allowing interaction below this. 461a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Setting newBlock will make sure we cancel the rest of the behaviors. 462a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final boolean wasBlocking = lp.didBlockInteraction(); 463a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final boolean isBlocking = lp.isBlockingInteractionBelow(this, child); 464a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell newBlock = isBlocking && !wasBlocking; 465a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (isBlocking && !newBlock) { 466a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Stop here since we don't have anything more to cancel - we already did 467a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // when the behavior first started blocking things below this point. 468a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 469a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 470a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 471a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 472a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell topmostChildList.clear(); 473a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 474a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return intercepted; 475a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 476a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 477a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 478a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean onInterceptTouchEvent(MotionEvent ev) { 479a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell MotionEvent cancelEvent = null; 480a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 48188cccf6c76b6a1c2d67152c2de5599f3c8301b18Chris Banes final int action = MotionEventCompat.getActionMasked(ev); 482a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 483a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Make sure we reset in case we had missed a previous important event. 484a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (action == MotionEvent.ACTION_DOWN) { 4855cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell resetTouchBehaviors(); 486a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 487a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 488d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes final boolean intercepted = performIntercept(ev, TYPE_ON_INTERCEPT); 489a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 490a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (cancelEvent != null) { 491a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell cancelEvent.recycle(); 492a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 493a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 494a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { 4955cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell resetTouchBehaviors(); 496a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 497a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 498a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return intercepted; 499a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 500a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 501a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 502a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean onTouchEvent(MotionEvent ev) { 503a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean handled = false; 504a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean cancelSuper = false; 505a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell MotionEvent cancelEvent = null; 506a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 50788cccf6c76b6a1c2d67152c2de5599f3c8301b18Chris Banes final int action = MotionEventCompat.getActionMasked(ev); 508a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 509d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes if (mBehaviorTouchView != null || (cancelSuper = performIntercept(ev, TYPE_ON_TOUCH))) { 510a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Safe since performIntercept guarantees that 511a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // mBehaviorTouchView != null if it returns true 512ecc58a45a7bdd60d9b71e6c413b80a3f8cf85822Chris Banes final LayoutParams lp = (LayoutParams) mBehaviorTouchView.getLayoutParams(); 513ecc58a45a7bdd60d9b71e6c413b80a3f8cf85822Chris Banes final Behavior b = lp.getBehavior(); 514ecc58a45a7bdd60d9b71e6c413b80a3f8cf85822Chris Banes if (b != null) { 515d4c72f08279df548fbc4d556fe1a8b3500fafdbcChris Banes handled = b.onTouchEvent(this, mBehaviorTouchView, ev); 516ecc58a45a7bdd60d9b71e6c413b80a3f8cf85822Chris Banes } 517a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 518a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 519a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Keep the super implementation correct 520a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mBehaviorTouchView == null) { 521a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell handled |= super.onTouchEvent(ev); 522a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else if (cancelSuper) { 523ea004a01f44aaf36212120c936952c1742d03d30Chris Banes if (cancelEvent == null) { 524a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final long now = SystemClock.uptimeMillis(); 525a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell cancelEvent = MotionEvent.obtain(now, now, 526a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0); 527a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 528a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell super.onTouchEvent(cancelEvent); 529a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 530a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 531a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (!handled && action == MotionEvent.ACTION_DOWN) { 532a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 533a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 534a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 535a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (cancelEvent != null) { 536a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell cancelEvent.recycle(); 537a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 538a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 539a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { 5405cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell resetTouchBehaviors(); 541a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 542a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 543a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return handled; 544a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 545a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 546a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 547a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) { 548a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell super.requestDisallowInterceptTouchEvent(disallowIntercept); 54978d6f4ad1fc1e2d57b138e31f47f2267731ee95eAurimas Liutikas if (disallowIntercept && !mDisallowInterceptReset) { 5505cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell resetTouchBehaviors(); 55178d6f4ad1fc1e2d57b138e31f47f2267731ee95eAurimas Liutikas mDisallowInterceptReset = true; 552a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 553a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 554a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 555a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private int getKeyline(int index) { 556a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mKeylines == null) { 557a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Log.e(TAG, "No keylines defined for " + this + " - attempted index lookup " + index); 558a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return 0; 559a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 560a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 561a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (index < 0 || index >= mKeylines.length) { 562a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Log.e(TAG, "Keyline index " + index + " out of range for " + this); 563a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return 0; 564a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 565a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 566a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return mKeylines[index]; 567a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 568a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 569a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell static Behavior parseBehavior(Context context, AttributeSet attrs, String name) { 570a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (TextUtils.isEmpty(name)) { 571a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return null; 572a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 573a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 574a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final String fullName; 575a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (name.startsWith(".")) { 576a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Relative to the app package. Prepend the app package name. 577a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell fullName = context.getPackageName() + name; 578a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else if (name.indexOf('.') >= 0) { 579a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Fully qualified package name. 580a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell fullName = name; 581a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else { 58225ef4026b72ff670ee07c81897124732d3f5f443Chris Banes // Assume stock behavior in this package (if we have one) 58325ef4026b72ff670ee07c81897124732d3f5f443Chris Banes fullName = !TextUtils.isEmpty(WIDGET_PACKAGE_NAME) 58425ef4026b72ff670ee07c81897124732d3f5f443Chris Banes ? (WIDGET_PACKAGE_NAME + '.' + name) 58525ef4026b72ff670ee07c81897124732d3f5f443Chris Banes : name; 586a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 587a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 588a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell try { 589a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Map<String, Constructor<Behavior>> constructors = sConstructors.get(); 590a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (constructors == null) { 591a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell constructors = new HashMap<>(); 592a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell sConstructors.set(constructors); 593a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 594a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Constructor<Behavior> c = constructors.get(fullName); 595a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (c == null) { 596a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Class<Behavior> clazz = (Class<Behavior>) Class.forName(fullName, true, 597a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell context.getClassLoader()); 598a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell c = clazz.getConstructor(CONSTRUCTOR_PARAMS); 599878384f1e6de7bd9196958224ced1ecfca3be6a7Chris Banes c.setAccessible(true); 600a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell constructors.put(fullName, c); 601a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 602a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return c.newInstance(context, attrs); 603a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } catch (Exception e) { 604a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell throw new RuntimeException("Could not inflate Behavior subclass " + fullName, e); 605a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 606a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 607a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 608a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell LayoutParams getResolvedLayoutParams(View child) { 609a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams result = (LayoutParams) child.getLayoutParams(); 610a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (!result.mBehaviorResolved) { 61142058bc54bdb89b9c9429bf6cbd3260787cf0523Adam Powell Class<?> childClass = child.getClass(); 61242058bc54bdb89b9c9429bf6cbd3260787cf0523Adam Powell DefaultBehavior defaultBehavior = null; 61342058bc54bdb89b9c9429bf6cbd3260787cf0523Adam Powell while (childClass != null && 61442058bc54bdb89b9c9429bf6cbd3260787cf0523Adam Powell (defaultBehavior = childClass.getAnnotation(DefaultBehavior.class)) == null) { 61542058bc54bdb89b9c9429bf6cbd3260787cf0523Adam Powell childClass = childClass.getSuperclass(); 61642058bc54bdb89b9c9429bf6cbd3260787cf0523Adam Powell } 617a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (defaultBehavior != null) { 618a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell try { 619a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell result.setBehavior(defaultBehavior.value().newInstance()); 620a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } catch (Exception e) { 621a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Log.e(TAG, "Default behavior class " + defaultBehavior.value().getName() + 622a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell " could not be instantiated. Did you forget a default constructor?", e); 623a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 624a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 625a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell result.mBehaviorResolved = true; 626a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 627a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return result; 628a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 629a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 6302f517207503fdffbcf930584a37b4a03392755d6Chris Banes private void prepareChildren() { 6318248a6287c4ff9fa71ff6760bb6fe0906f0d6607Chris Banes mDependencySortedChildren.clear(); 632a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes mChildDag.clear(); 633a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes 6348248a6287c4ff9fa71ff6760bb6fe0906f0d6607Chris Banes for (int i = 0, count = getChildCount(); i < count; i++) { 635a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes final View view = getChildAt(i); 6368248a6287c4ff9fa71ff6760bb6fe0906f0d6607Chris Banes 637a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes final LayoutParams lp = getResolvedLayoutParams(view); 638a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes lp.findAnchorView(this, view); 639a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 640a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes mChildDag.addNode(view); 641a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes 642a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes // Now iterate again over the other children, adding any dependencies to the graph 643a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes for (int j = 0; j < count; j++) { 644a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes if (j == i) { 645a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes continue; 646a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes } 647a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes final View other = getChildAt(j); 648a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes final LayoutParams otherLp = getResolvedLayoutParams(other); 649a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes if (otherLp.dependsOn(this, other, view)) { 650a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes if (!mChildDag.contains(other)) { 651a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes // Make sure that the other node is added 652a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes mChildDag.addNode(other); 653a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes } 654a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes // Now add the dependency to the graph 655a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes mChildDag.addEdge(view, other); 656a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes } 657a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes } 658a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 659a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes 660a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes // Finally add the sorted graph list to our list 661a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes mDependencySortedChildren.addAll(mChildDag.getSortedList()); 662a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes // We also need to reverse the result since we want the start of the list to contain 663a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes // Views which have no dependencies, then dependent views after that 664a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes Collections.reverse(mDependencySortedChildren); 665a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 666a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 667a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 668a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Retrieve the transformed bounding rect of an arbitrary descendant view. 669a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * This does not need to be a direct child. 670a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 671a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param descendant descendant view to reference 672a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param out rect to set to the bounds of the descendant view 673a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 674a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void getDescendantRect(View descendant, Rect out) { 675a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes ViewGroupUtils.getDescendantRect(this, descendant, out); 676a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 677a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 678a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 679a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell protected int getSuggestedMinimumWidth() { 680a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return Math.max(super.getSuggestedMinimumWidth(), getPaddingLeft() + getPaddingRight()); 681a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 682a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 683a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 684a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell protected int getSuggestedMinimumHeight() { 685a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return Math.max(super.getSuggestedMinimumHeight(), getPaddingTop() + getPaddingBottom()); 686a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 687a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 688a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 689a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Called to measure each individual child view unless a 690a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link CoordinatorLayout.Behavior Behavior} is present. The Behavior may choose to delegate 691a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * child measurement to this method. 692a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 693a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child to measure 694a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parentWidthMeasureSpec the width requirements for this view 695a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param widthUsed extra space that has been used up by the parent 696a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * horizontally (possibly by other children of the parent) 697a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parentHeightMeasureSpec the height requirements for this view 698a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param heightUsed extra space that has been used up by the parent 699a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * vertically (possibly by other children of the parent) 700a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 701a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public void onMeasureChild(View child, int parentWidthMeasureSpec, int widthUsed, 702a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int parentHeightMeasureSpec, int heightUsed) { 703a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell measureChildWithMargins(child, parentWidthMeasureSpec, widthUsed, 704a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell parentHeightMeasureSpec, heightUsed); 705a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 706a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 707a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 708a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 7092f517207503fdffbcf930584a37b4a03392755d6Chris Banes prepareChildren(); 710a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell ensurePreDrawListener(); 711a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 712a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int paddingLeft = getPaddingLeft(); 713a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int paddingTop = getPaddingTop(); 714a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int paddingRight = getPaddingRight(); 715a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int paddingBottom = getPaddingBottom(); 716a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int layoutDirection = ViewCompat.getLayoutDirection(this); 717a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final boolean isRtl = layoutDirection == ViewCompat.LAYOUT_DIRECTION_RTL; 718a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int widthMode = MeasureSpec.getMode(widthMeasureSpec); 719a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int widthSize = MeasureSpec.getSize(widthMeasureSpec); 72075284fffafacd32f4d178020050589f9e70e5ed9Chris Banes final int heightMode = MeasureSpec.getMode(heightMeasureSpec); 72175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes final int heightSize = MeasureSpec.getSize(heightMeasureSpec); 722a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 723a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int widthPadding = paddingLeft + paddingRight; 724a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int heightPadding = paddingTop + paddingBottom; 725a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int widthUsed = getSuggestedMinimumWidth(); 726a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int heightUsed = getSuggestedMinimumHeight(); 727a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int childState = 0; 728a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 72975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes final boolean applyInsets = mLastInsets != null && ViewCompat.getFitsSystemWindows(this); 73075284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 731a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childCount = mDependencySortedChildren.size(); 732a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int i = 0; i < childCount; i++) { 733a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final View child = mDependencySortedChildren.get(i); 734a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 735a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 736a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int keylineWidthUsed = 0; 737a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (lp.keyline >= 0 && widthMode != MeasureSpec.UNSPECIFIED) { 738a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int keylinePos = getKeyline(lp.keyline); 739a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int keylineGravity = GravityCompat.getAbsoluteGravity( 740a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell resolveKeylineGravity(lp.gravity), layoutDirection) 741a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell & Gravity.HORIZONTAL_GRAVITY_MASK; 742a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if ((keylineGravity == Gravity.LEFT && !isRtl) 743a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell || (keylineGravity == Gravity.RIGHT && isRtl)) { 744a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell keylineWidthUsed = Math.max(0, widthSize - paddingRight - keylinePos); 745a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else if ((keylineGravity == Gravity.RIGHT && !isRtl) 746a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell || (keylineGravity == Gravity.LEFT && isRtl)) { 747a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell keylineWidthUsed = Math.max(0, keylinePos - paddingLeft); 748a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 749a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 750a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 75175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes int childWidthMeasureSpec = widthMeasureSpec; 75275284fffafacd32f4d178020050589f9e70e5ed9Chris Banes int childHeightMeasureSpec = heightMeasureSpec; 75375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes if (applyInsets && !ViewCompat.getFitsSystemWindows(child)) { 75475284fffafacd32f4d178020050589f9e70e5ed9Chris Banes // We're set to handle insets but this child isn't, so we will measure the 75575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes // child as if there are no insets 75675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes final int horizInsets = mLastInsets.getSystemWindowInsetLeft() 75775284fffafacd32f4d178020050589f9e70e5ed9Chris Banes + mLastInsets.getSystemWindowInsetRight(); 75875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes final int vertInsets = mLastInsets.getSystemWindowInsetTop() 75975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes + mLastInsets.getSystemWindowInsetBottom(); 76075284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 76175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes childWidthMeasureSpec = MeasureSpec.makeMeasureSpec( 76275284fffafacd32f4d178020050589f9e70e5ed9Chris Banes widthSize - horizInsets, widthMode); 76375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes childHeightMeasureSpec = MeasureSpec.makeMeasureSpec( 76475284fffafacd32f4d178020050589f9e70e5ed9Chris Banes heightSize - vertInsets, heightMode); 76575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 76675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 767a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Behavior b = lp.getBehavior(); 76875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes if (b == null || !b.onMeasureChild(this, child, childWidthMeasureSpec, keylineWidthUsed, 76975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes childHeightMeasureSpec, 0)) { 77075284fffafacd32f4d178020050589f9e70e5ed9Chris Banes onMeasureChild(child, childWidthMeasureSpec, keylineWidthUsed, 77175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes childHeightMeasureSpec, 0); 772a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 773a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 774a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell widthUsed = Math.max(widthUsed, widthPadding + child.getMeasuredWidth() + 775a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell lp.leftMargin + lp.rightMargin); 776a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 777a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell heightUsed = Math.max(heightUsed, heightPadding + child.getMeasuredHeight() + 778a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell lp.topMargin + lp.bottomMargin); 779a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell childState = ViewCompat.combineMeasuredStates(childState, 780a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell ViewCompat.getMeasuredState(child)); 781a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 782a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 783a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int width = ViewCompat.resolveSizeAndState(widthUsed, widthMeasureSpec, 784a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell childState & ViewCompat.MEASURED_STATE_MASK); 785a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int height = ViewCompat.resolveSizeAndState(heightUsed, heightMeasureSpec, 786a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell childState << ViewCompat.MEASURED_HEIGHT_STATE_SHIFT); 787a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell setMeasuredDimension(width, height); 788a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 789a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 79017ed3263761329f6aa6796941358c41001fff325Chris Banes private WindowInsetsCompat dispatchApplyWindowInsetsToBehaviors(WindowInsetsCompat insets) { 79175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes if (insets.isConsumed()) { 79217ed3263761329f6aa6796941358c41001fff325Chris Banes return insets; 79375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 79475284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 79575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes for (int i = 0, z = getChildCount(); i < z; i++) { 79675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes final View child = getChildAt(i); 79775284fffafacd32f4d178020050589f9e70e5ed9Chris Banes if (ViewCompat.getFitsSystemWindows(child)) { 79875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 79975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes final Behavior b = lp.getBehavior(); 80075284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 80175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes if (b != null) { 80275284fffafacd32f4d178020050589f9e70e5ed9Chris Banes // If the view has a behavior, let it try first 80375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes insets = b.onApplyWindowInsets(this, child, insets); 80475284fffafacd32f4d178020050589f9e70e5ed9Chris Banes if (insets.isConsumed()) { 80575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes // If it consumed the insets, break 80675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes break; 80775284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 80875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 80975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 81075284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 81117ed3263761329f6aa6796941358c41001fff325Chris Banes 81217ed3263761329f6aa6796941358c41001fff325Chris Banes return insets; 81375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 81475284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 815a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 816a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Called to lay out each individual child view unless a 817a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link CoordinatorLayout.Behavior Behavior} is present. The Behavior may choose to 818a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * delegate child measurement to this method. 819a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 820a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child view to lay out 821a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param layoutDirection the resolved layout direction for the CoordinatorLayout, such as 822a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link ViewCompat#LAYOUT_DIRECTION_LTR} or 823a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link ViewCompat#LAYOUT_DIRECTION_RTL}. 824a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 825a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public void onLayoutChild(View child, int layoutDirection) { 826a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 827a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (lp.checkAnchorChanged()) { 828a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell throw new IllegalStateException("An anchor may not be changed after CoordinatorLayout" 829a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell + " measurement begins before layout is complete."); 830a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 831a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (lp.mAnchorView != null) { 832a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell layoutChildWithAnchor(child, lp.mAnchorView, layoutDirection); 833a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else if (lp.keyline >= 0) { 834a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell layoutChildWithKeyline(child, lp.keyline, layoutDirection); 835a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else { 836a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell layoutChild(child, layoutDirection); 837a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 838a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 839a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 840a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 841a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell protected void onLayout(boolean changed, int l, int t, int r, int b) { 842a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int layoutDirection = ViewCompat.getLayoutDirection(this); 843a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childCount = mDependencySortedChildren.size(); 844a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int i = 0; i < childCount; i++) { 845a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final View child = mDependencySortedChildren.get(i); 846a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 847a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Behavior behavior = lp.getBehavior(); 848a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 849a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (behavior == null || !behavior.onLayoutChild(this, child, layoutDirection)) { 850a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell onLayoutChild(child, layoutDirection); 851a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 852a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 853a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 854a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 85575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes @Override 85675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes public void onDraw(Canvas c) { 85775284fffafacd32f4d178020050589f9e70e5ed9Chris Banes super.onDraw(c); 85875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes if (mDrawStatusBarBackground && mStatusBarBackground != null) { 85975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes final int inset = mLastInsets != null ? mLastInsets.getSystemWindowInsetTop() : 0; 86075284fffafacd32f4d178020050589f9e70e5ed9Chris Banes if (inset > 0) { 86175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes mStatusBarBackground.setBounds(0, 0, getWidth(), inset); 86275284fffafacd32f4d178020050589f9e70e5ed9Chris Banes mStatusBarBackground.draw(c); 86375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 86475284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 86575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 86675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 8673035e10317eb12c58153d8c651a791896ea3094eChris Banes @Override 8683035e10317eb12c58153d8c651a791896ea3094eChris Banes public void setFitsSystemWindows(boolean fitSystemWindows) { 8693035e10317eb12c58153d8c651a791896ea3094eChris Banes super.setFitsSystemWindows(fitSystemWindows); 8703035e10317eb12c58153d8c651a791896ea3094eChris Banes setupForInsets(); 8713035e10317eb12c58153d8c651a791896ea3094eChris Banes } 8723035e10317eb12c58153d8c651a791896ea3094eChris Banes 873a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 874a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Mark the last known child position rect for the given child view. 875a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * This will be used when checking if a child view's position has changed between frames. 876a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * The rect used here should be one returned by 877a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link #getChildRect(android.view.View, boolean, android.graphics.Rect)}, with translation 878a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * disabled. 879a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 880a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child view to set for 881a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param r rect to set 882a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 883a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void recordLastChildRect(View child, Rect r) { 884a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 885a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell lp.setLastChildRect(r); 886a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 887a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 888a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 889a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Get the last known child rect recorded by 890a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link #recordLastChildRect(android.view.View, android.graphics.Rect)}. 891a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 892a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child view to retrieve from 893a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param out rect to set to the outpur values 894a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 895a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void getLastChildRect(View child, Rect out) { 896a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 897a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell out.set(lp.getLastChildRect()); 898a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 899a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 900a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 901a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Get the position rect for the given child. If the child has currently requested layout 902a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * or has a visibility of GONE. 903a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 904a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child view to check 905a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param transform true to include transformation in the output rect, false to 906a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * only account for the base position 907a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param out rect to set to the output values 908a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 909a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void getChildRect(View child, boolean transform, Rect out) { 910a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (child.isLayoutRequested() || child.getVisibility() == View.GONE) { 91126c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes out.setEmpty(); 912a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return; 913a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 914a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (transform) { 915a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getDescendantRect(child, out); 916a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else { 917a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell out.set(child.getLeft(), child.getTop(), child.getRight(), child.getBottom()); 918a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 919a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 920a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 9218f8034a4204fc10c4805758051f0cec2159c0e40Yuichi Araki private void getDesiredAnchoredChildRectWithoutConstraints(View child, int layoutDirection, 9228f8034a4204fc10c4805758051f0cec2159c0e40Yuichi Araki Rect anchorRect, Rect out, LayoutParams lp, int childWidth, int childHeight) { 923a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int absGravity = GravityCompat.getAbsoluteGravity( 924a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell resolveAnchoredChildGravity(lp.gravity), layoutDirection); 925a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int absAnchorGravity = GravityCompat.getAbsoluteGravity( 926a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell resolveGravity(lp.anchorGravity), 927a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell layoutDirection); 928a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 929a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int hgrav = absGravity & Gravity.HORIZONTAL_GRAVITY_MASK; 930a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int vgrav = absGravity & Gravity.VERTICAL_GRAVITY_MASK; 931a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int anchorHgrav = absAnchorGravity & Gravity.HORIZONTAL_GRAVITY_MASK; 932a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int anchorVgrav = absAnchorGravity & Gravity.VERTICAL_GRAVITY_MASK; 933a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 934a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int left; 935a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int top; 936a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 937d09e24f8d4c10e72dee0e435d3289ddd10223aa0Adam Powell // Align to the anchor. This puts us in an assumed right/bottom child view gravity. 938d09e24f8d4c10e72dee0e435d3289ddd10223aa0Adam Powell // If this is not the case we will subtract out the appropriate portion of 939d09e24f8d4c10e72dee0e435d3289ddd10223aa0Adam Powell // the child size below. 940a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell switch (anchorHgrav) { 941a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell default: 942a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.LEFT: 943a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell left = anchorRect.left; 944a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 945a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.RIGHT: 946d09e24f8d4c10e72dee0e435d3289ddd10223aa0Adam Powell left = anchorRect.right; 947a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 948a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.CENTER_HORIZONTAL: 949d09e24f8d4c10e72dee0e435d3289ddd10223aa0Adam Powell left = anchorRect.left + anchorRect.width() / 2; 950a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 951a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 952a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 953a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell switch (anchorVgrav) { 954a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell default: 955a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.TOP: 956a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell top = anchorRect.top; 957a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 958a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.BOTTOM: 959d09e24f8d4c10e72dee0e435d3289ddd10223aa0Adam Powell top = anchorRect.bottom; 960a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 961a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.CENTER_VERTICAL: 962d09e24f8d4c10e72dee0e435d3289ddd10223aa0Adam Powell top = anchorRect.top + anchorRect.height() / 2; 963a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 964a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 965a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 966d09e24f8d4c10e72dee0e435d3289ddd10223aa0Adam Powell // Offset by the child view's gravity itself. The above assumed right/bottom gravity. 967a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell switch (hgrav) { 968a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell default: 969a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.LEFT: 970d09e24f8d4c10e72dee0e435d3289ddd10223aa0Adam Powell left -= childWidth; 971a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 972a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.RIGHT: 973d09e24f8d4c10e72dee0e435d3289ddd10223aa0Adam Powell // Do nothing, we're already in position. 974a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 975a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.CENTER_HORIZONTAL: 976d09e24f8d4c10e72dee0e435d3289ddd10223aa0Adam Powell left -= childWidth / 2; 977a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 978a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 979a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 980a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell switch (vgrav) { 981a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell default: 982a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.TOP: 983d09e24f8d4c10e72dee0e435d3289ddd10223aa0Adam Powell top -= childHeight; 984a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 985a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.BOTTOM: 986d09e24f8d4c10e72dee0e435d3289ddd10223aa0Adam Powell // Do nothing, we're already in position. 987a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 988a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.CENTER_VERTICAL: 989d09e24f8d4c10e72dee0e435d3289ddd10223aa0Adam Powell top -= childHeight / 2; 990a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 991a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 992a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 9938f8034a4204fc10c4805758051f0cec2159c0e40Yuichi Araki out.set(left, top, left + childWidth, top + childHeight); 9948f8034a4204fc10c4805758051f0cec2159c0e40Yuichi Araki } 9958f8034a4204fc10c4805758051f0cec2159c0e40Yuichi Araki 9968f8034a4204fc10c4805758051f0cec2159c0e40Yuichi Araki private void constrainChildRect(LayoutParams lp, Rect out, int childWidth, int childHeight) { 997a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int width = getWidth(); 998a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int height = getHeight(); 999a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1000a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Obey margins and padding 10018f8034a4204fc10c4805758051f0cec2159c0e40Yuichi Araki int left = Math.max(getPaddingLeft() + lp.leftMargin, 10028f8034a4204fc10c4805758051f0cec2159c0e40Yuichi Araki Math.min(out.left, 1003a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell width - getPaddingRight() - childWidth - lp.rightMargin)); 10048f8034a4204fc10c4805758051f0cec2159c0e40Yuichi Araki int top = Math.max(getPaddingTop() + lp.topMargin, 10058f8034a4204fc10c4805758051f0cec2159c0e40Yuichi Araki Math.min(out.top, 1006a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell height - getPaddingBottom() - childHeight - lp.bottomMargin)); 1007a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1008a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell out.set(left, top, left + childWidth, top + childHeight); 1009a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1010a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1011a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 10128f8034a4204fc10c4805758051f0cec2159c0e40Yuichi Araki * Calculate the desired child rect relative to an anchor rect, respecting both 10138f8034a4204fc10c4805758051f0cec2159c0e40Yuichi Araki * gravity and anchorGravity. 10148f8034a4204fc10c4805758051f0cec2159c0e40Yuichi Araki * 10158f8034a4204fc10c4805758051f0cec2159c0e40Yuichi Araki * @param child child view to calculate a rect for 10168f8034a4204fc10c4805758051f0cec2159c0e40Yuichi Araki * @param layoutDirection the desired layout direction for the CoordinatorLayout 10178f8034a4204fc10c4805758051f0cec2159c0e40Yuichi Araki * @param anchorRect rect in CoordinatorLayout coordinates of the anchor view area 10188f8034a4204fc10c4805758051f0cec2159c0e40Yuichi Araki * @param out rect to set to the output values 10198f8034a4204fc10c4805758051f0cec2159c0e40Yuichi Araki */ 10208f8034a4204fc10c4805758051f0cec2159c0e40Yuichi Araki void getDesiredAnchoredChildRect(View child, int layoutDirection, Rect anchorRect, Rect out) { 10218f8034a4204fc10c4805758051f0cec2159c0e40Yuichi Araki final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 10228f8034a4204fc10c4805758051f0cec2159c0e40Yuichi Araki final int childWidth = child.getMeasuredWidth(); 10238f8034a4204fc10c4805758051f0cec2159c0e40Yuichi Araki final int childHeight = child.getMeasuredHeight(); 10248f8034a4204fc10c4805758051f0cec2159c0e40Yuichi Araki getDesiredAnchoredChildRectWithoutConstraints(child, layoutDirection, anchorRect, out, lp, 10258f8034a4204fc10c4805758051f0cec2159c0e40Yuichi Araki childWidth, childHeight); 10268f8034a4204fc10c4805758051f0cec2159c0e40Yuichi Araki constrainChildRect(lp, out, childWidth, childHeight); 10278f8034a4204fc10c4805758051f0cec2159c0e40Yuichi Araki } 10288f8034a4204fc10c4805758051f0cec2159c0e40Yuichi Araki 10298f8034a4204fc10c4805758051f0cec2159c0e40Yuichi Araki /** 1030a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * CORE ASSUMPTION: anchor has been laid out by the time this is called for a given child view. 1031a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1032a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child to lay out 1033a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param anchor view to anchor child relative to; already laid out. 1034a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param layoutDirection ViewCompat constant for layout direction 1035a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1036a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private void layoutChildWithAnchor(View child, View anchor, int layoutDirection) { 1037a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 1038a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1039a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Rect anchorRect = mTempRect1; 1040a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Rect childRect = mTempRect2; 1041a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getDescendantRect(anchor, anchorRect); 1042a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getDesiredAnchoredChildRect(child, layoutDirection, anchorRect, childRect); 1043a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1044a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell child.layout(childRect.left, childRect.top, childRect.right, childRect.bottom); 1045a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1046a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1047a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1048a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Lay out a child view with respect to a keyline. 1049a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1050a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>The keyline represents a horizontal offset from the unpadded starting edge of 1051a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * the CoordinatorLayout. The child's gravity will affect how it is positioned with 1052a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * respect to the keyline.</p> 1053a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1054a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child to lay out 1055a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param keyline offset from the starting edge in pixels of the keyline to align with 1056a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param layoutDirection ViewCompat constant for layout direction 1057a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1058a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private void layoutChildWithKeyline(View child, int keyline, int layoutDirection) { 1059a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 1060a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int absGravity = GravityCompat.getAbsoluteGravity( 1061a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell resolveKeylineGravity(lp.gravity), layoutDirection); 1062a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1063a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int hgrav = absGravity & Gravity.HORIZONTAL_GRAVITY_MASK; 1064a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int vgrav = absGravity & Gravity.VERTICAL_GRAVITY_MASK; 1065a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int width = getWidth(); 1066a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int height = getHeight(); 1067a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childWidth = child.getMeasuredWidth(); 1068a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childHeight = child.getMeasuredHeight(); 1069a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1070a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (layoutDirection == ViewCompat.LAYOUT_DIRECTION_RTL) { 1071a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell keyline = width - keyline; 1072a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1073a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1074a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int left = getKeyline(keyline) - childWidth; 1075a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int top = 0; 1076a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1077a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell switch (hgrav) { 1078a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell default: 1079a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.LEFT: 1080a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Nothing to do. 1081a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 1082a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.RIGHT: 1083a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell left += childWidth; 1084a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 1085a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.CENTER_HORIZONTAL: 1086a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell left += childWidth / 2; 1087a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 1088a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1089a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1090a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell switch (vgrav) { 1091a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell default: 1092a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.TOP: 1093a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Do nothing, we're already in position. 1094a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 1095a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.BOTTOM: 1096a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell top += childHeight; 1097a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 1098a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell case Gravity.CENTER_VERTICAL: 1099a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell top += childHeight / 2; 1100a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 1101a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1102a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1103a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Obey margins and padding 1104a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell left = Math.max(getPaddingLeft() + lp.leftMargin, 1105a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Math.min(left, 1106a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell width - getPaddingRight() - childWidth - lp.rightMargin)); 1107a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell top = Math.max(getPaddingTop() + lp.topMargin, 1108a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Math.min(top, 1109a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell height - getPaddingBottom() - childHeight - lp.bottomMargin)); 1110a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1111a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell child.layout(left, top, left + childWidth, top + childHeight); 1112a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1113a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1114a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1115a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Lay out a child view with no special handling. This will position the child as 1116a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * if it were within a FrameLayout or similar simple frame. 1117a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1118a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child view to lay out 1119a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param layoutDirection ViewCompat constant for the desired layout direction 1120a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1121a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private void layoutChild(View child, int layoutDirection) { 1122a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 1123a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Rect parent = mTempRect1; 1124a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell parent.set(getPaddingLeft() + lp.leftMargin, 1125a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getPaddingTop() + lp.topMargin, 1126a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getWidth() - getPaddingRight() - lp.rightMargin, 1127a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getHeight() - getPaddingBottom() - lp.bottomMargin); 112875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 112975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes if (mLastInsets != null && ViewCompat.getFitsSystemWindows(this) 113075284fffafacd32f4d178020050589f9e70e5ed9Chris Banes && !ViewCompat.getFitsSystemWindows(child)) { 113175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes // If we're set to handle insets but this child isn't, then it has been measured as 113275284fffafacd32f4d178020050589f9e70e5ed9Chris Banes // if there are no insets. We need to lay it out to match. 113375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes parent.left += mLastInsets.getSystemWindowInsetLeft(); 113475284fffafacd32f4d178020050589f9e70e5ed9Chris Banes parent.top += mLastInsets.getSystemWindowInsetTop(); 113575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes parent.right -= mLastInsets.getSystemWindowInsetRight(); 113675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes parent.bottom -= mLastInsets.getSystemWindowInsetBottom(); 113775284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 113875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 1139a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Rect out = mTempRect2; 1140a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell GravityCompat.apply(resolveGravity(lp.gravity), child.getMeasuredWidth(), 1141a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell child.getMeasuredHeight(), parent, out, layoutDirection); 1142a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell child.layout(out.left, out.top, out.right, out.bottom); 1143a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1144a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1145a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1146a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Return the given gravity value or the default if the passed value is NO_GRAVITY. 1147a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * This should be used for children that are not anchored to another view or a keyline. 1148a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1149a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private static int resolveGravity(int gravity) { 1150a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return gravity == Gravity.NO_GRAVITY ? GravityCompat.START | Gravity.TOP : gravity; 1151a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1152a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1153a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1154a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Return the given gravity value or the default if the passed value is NO_GRAVITY. 1155a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * This should be used for children that are positioned relative to a keyline. 1156a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1157a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private static int resolveKeylineGravity(int gravity) { 1158a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return gravity == Gravity.NO_GRAVITY ? GravityCompat.END | Gravity.TOP : gravity; 1159a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1160a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1161a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1162a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Return the given gravity value or the default if the passed value is NO_GRAVITY. 1163a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * This should be used for children that are anchored to another view. 1164a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1165a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private static int resolveAnchoredChildGravity(int gravity) { 1166a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return gravity == Gravity.NO_GRAVITY ? Gravity.CENTER : gravity; 1167a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1168a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1169a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 1170a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell protected boolean drawChild(Canvas canvas, View child, long drawingTime) { 1171a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 1172b806673aa0977685995be820981207f6bf51858bChris Banes if (lp.mBehavior != null) { 1173b806673aa0977685995be820981207f6bf51858bChris Banes final float scrimAlpha = lp.mBehavior.getScrimOpacity(this, child); 1174b806673aa0977685995be820981207f6bf51858bChris Banes if (scrimAlpha > 0f) { 1175b806673aa0977685995be820981207f6bf51858bChris Banes if (mScrimPaint == null) { 1176b806673aa0977685995be820981207f6bf51858bChris Banes mScrimPaint = new Paint(); 1177b806673aa0977685995be820981207f6bf51858bChris Banes } 1178b806673aa0977685995be820981207f6bf51858bChris Banes mScrimPaint.setColor(lp.mBehavior.getScrimColor(this, child)); 1179b806673aa0977685995be820981207f6bf51858bChris Banes mScrimPaint.setAlpha(MathUtils.constrain(Math.round(255 * scrimAlpha), 0, 255)); 1180b806673aa0977685995be820981207f6bf51858bChris Banes 1181b806673aa0977685995be820981207f6bf51858bChris Banes final int saved = canvas.save(); 1182b806673aa0977685995be820981207f6bf51858bChris Banes if (child.isOpaque()) { 1183b806673aa0977685995be820981207f6bf51858bChris Banes // If the child is opaque, there is no need to draw behind it so we'll inverse 1184b806673aa0977685995be820981207f6bf51858bChris Banes // clip the canvas 1185b806673aa0977685995be820981207f6bf51858bChris Banes canvas.clipRect(child.getLeft(), child.getTop(), child.getRight(), 1186b806673aa0977685995be820981207f6bf51858bChris Banes child.getBottom(), Region.Op.DIFFERENCE); 1187b806673aa0977685995be820981207f6bf51858bChris Banes } 1188b806673aa0977685995be820981207f6bf51858bChris Banes // Now draw the rectangle for the scrim 1189b806673aa0977685995be820981207f6bf51858bChris Banes canvas.drawRect(getPaddingLeft(), getPaddingTop(), 1190b806673aa0977685995be820981207f6bf51858bChris Banes getWidth() - getPaddingRight(), getHeight() - getPaddingBottom(), 1191b806673aa0977685995be820981207f6bf51858bChris Banes mScrimPaint); 1192b806673aa0977685995be820981207f6bf51858bChris Banes canvas.restoreToCount(saved); 1193a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1194a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1195a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return super.drawChild(canvas, child, drawingTime); 1196a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1197a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1198a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1199a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * Dispatch any dependent view changes to the relevant {@link Behavior} instances. 1200a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * 1201a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * Usually run as part of the pre-draw step when at least one child view has a reported 1202a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * dependency on another view. This allows CoordinatorLayout to account for layout 1203a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * changes and animations that occur outside of the normal layout pass. 1204a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1205a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * It can also be ran as part of the nested scrolling dispatch to ensure that any offsetting 1206a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * is completed within the correct coordinate window. 1207a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * 1208a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * The offsetting behavior implemented here does not store the computed offset in 1209a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * the LayoutParams; instead it expects that the layout process will always reconstruct 1210a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * the proper positioning. 1211a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * 121226c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes * @param type the type of event which has caused this call 1213a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 121426c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes final void onChildViewsChanged(@DispatchChangeEvent final int type) { 1215a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int layoutDirection = ViewCompat.getLayoutDirection(this); 1216a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childCount = mDependencySortedChildren.size(); 1217943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki final Rect inset = mTempRect4; 1218943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki inset.setEmpty(); 1219a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int i = 0; i < childCount; i++) { 1220a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final View child = mDependencySortedChildren.get(i); 1221a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 1222a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1223a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Check child views before for anchor 1224a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int j = 0; j < i; j++) { 1225a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final View checkChild = mDependencySortedChildren.get(j); 1226a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1227a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (lp.mAnchorDirectChild == checkChild) { 1228a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell offsetChildToAnchor(child, layoutDirection); 1229a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1230a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1231a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 123226c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes // Get the current draw rect of the view 123326c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes final Rect drawRect = mTempRect1; 123426c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes getChildRect(child, true, drawRect); 123526c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes 1236943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki // Accumulate inset sizes 123726c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes if (lp.insetEdge != Gravity.NO_GRAVITY && !drawRect.isEmpty()) { 1238943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki final int absInsetEdge = GravityCompat.getAbsoluteGravity( 1239943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki lp.insetEdge, layoutDirection); 124026c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes switch (absInsetEdge & Gravity.VERTICAL_GRAVITY_MASK) { 1241943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki case Gravity.TOP: 124226c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes inset.top = Math.max(inset.top, drawRect.bottom); 1243943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki break; 1244943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki case Gravity.BOTTOM: 124526c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes inset.bottom = Math.max(inset.bottom, getHeight() - drawRect.top); 1246943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki break; 124726c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes } 124826c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes switch (absInsetEdge & Gravity.HORIZONTAL_GRAVITY_MASK) { 1249943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki case Gravity.LEFT: 125026c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes inset.left = Math.max(inset.left, drawRect.right); 1251943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki break; 1252943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki case Gravity.RIGHT: 125326c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes inset.right = Math.max(inset.right, getWidth() - drawRect.left); 1254943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki break; 1255943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki } 1256943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki } 1257943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki 1258943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki // Dodge inset edges if necessary 12596f5e71c633625183188ddd567bab27e8b81c6bffChris Banes if (lp.dodgeInsetEdges != Gravity.NO_GRAVITY && child.getVisibility() == View.VISIBLE) { 1260943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki offsetChildByInset(child, inset, layoutDirection); 1261943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki } 1262943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki 12633c9fb156e6585049f4e8f7992542aca307f0be13Chris Banes if (type == EVENT_PRE_DRAW) { 12643c9fb156e6585049f4e8f7992542aca307f0be13Chris Banes // Did it change? if not continue 12653c9fb156e6585049f4e8f7992542aca307f0be13Chris Banes final Rect lastDrawRect = mTempRect2; 12663c9fb156e6585049f4e8f7992542aca307f0be13Chris Banes getLastChildRect(child, lastDrawRect); 12673c9fb156e6585049f4e8f7992542aca307f0be13Chris Banes if (lastDrawRect.equals(drawRect)) { 12683c9fb156e6585049f4e8f7992542aca307f0be13Chris Banes continue; 12693c9fb156e6585049f4e8f7992542aca307f0be13Chris Banes } 12703c9fb156e6585049f4e8f7992542aca307f0be13Chris Banes recordLastChildRect(child, drawRect); 1271a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1272a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1273a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Update any behavior-dependent views for the change 1274a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int j = i + 1; j < childCount; j++) { 1275a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final View checkChild = mDependencySortedChildren.get(j); 1276a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams checkLp = (LayoutParams) checkChild.getLayoutParams(); 1277a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Behavior b = checkLp.getBehavior(); 1278a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1279a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (b != null && b.layoutDependsOn(this, checkChild, child)) { 128026c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes if (type == EVENT_PRE_DRAW && checkLp.getChangedAfterNestedScroll()) { 128126c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes // If this is from a pre-draw and we have already been changed 1282a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes // from a nested scroll, skip the dispatch and reset the flag 1283a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes checkLp.resetChangedAfterNestedScroll(); 1284a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes continue; 1285a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1286a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 128726c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes final boolean handled; 128826c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes switch (type) { 128926c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes case EVENT_VIEW_REMOVED: 129026c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes // EVENT_VIEW_REMOVED means that we need to dispatch 129126c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes // onDependentViewRemoved() instead 129226c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes b.onDependentViewRemoved(this, checkChild, child); 129326c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes handled = true; 129426c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes break; 129526c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes default: 129626c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes // Otherwise we dispatch onDependentViewChanged() 129726c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes handled = b.onDependentViewChanged(this, checkChild, child); 129826c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes break; 129926c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes } 1300a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 130126c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes if (type == EVENT_NESTED_SCROLL) { 1302a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes // If this is from a nested scroll, set the flag so that we may skip 1303a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes // any resulting onPreDraw dispatch (if needed) 1304a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes checkLp.setChangedAfterNestedScroll(handled); 1305a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1306a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1307a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1308a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1309a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1310a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 13116f5e71c633625183188ddd567bab27e8b81c6bffChris Banes private void offsetChildByInset(final View child, final Rect inset, final int layoutDirection) { 1312f42b1d01133891273cc97ccf37e86e899f7e62b1Alan Viverette if (!ViewCompat.isLaidOut(child)) { 1313f42b1d01133891273cc97ccf37e86e899f7e62b1Alan Viverette // The view has not been laid out yet, 1314f42b1d01133891273cc97ccf37e86e899f7e62b1Alan Viverette // so we can't obtain its bounds. 1315f42b1d01133891273cc97ccf37e86e899f7e62b1Alan Viverette return; 1316f42b1d01133891273cc97ccf37e86e899f7e62b1Alan Viverette } 1317f42b1d01133891273cc97ccf37e86e899f7e62b1Alan Viverette 13186206ad57276146c8f70e939fd40ce9c7b88767f6Yuichi Araki final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 1319943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki final int absDodgeInsetEdges = GravityCompat.getAbsoluteGravity(lp.dodgeInsetEdges, 1320943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki layoutDirection); 132126c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes 132226c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes final Behavior behavior = lp.getBehavior(); 132326c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes final Rect rect = mTempRect3; 132426c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes if (behavior != null && behavior.getInsetDodgeRect(this, child, rect)) { 132526c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes // Make sure that it intersects the views bounds 13266f5e71c633625183188ddd567bab27e8b81c6bffChris Banes if (!rect.intersect(child.getLeft(), child.getTop(), 13276f5e71c633625183188ddd567bab27e8b81c6bffChris Banes child.getRight(), child.getBottom())) { 13286f5e71c633625183188ddd567bab27e8b81c6bffChris Banes throw new IllegalArgumentException("Rect should intersect with child's bounds."); 13296f5e71c633625183188ddd567bab27e8b81c6bffChris Banes } 133026c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes } else { 133126c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes rect.set(child.getLeft(), child.getTop(), child.getRight(), child.getBottom()); 1332943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki } 133326c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes 13346f5e71c633625183188ddd567bab27e8b81c6bffChris Banes if (rect.isEmpty()) { 13356f5e71c633625183188ddd567bab27e8b81c6bffChris Banes // Rect is empty so there is nothing to dodge against, skip... 13366f5e71c633625183188ddd567bab27e8b81c6bffChris Banes return; 13376f5e71c633625183188ddd567bab27e8b81c6bffChris Banes } 13386f5e71c633625183188ddd567bab27e8b81c6bffChris Banes 13396206ad57276146c8f70e939fd40ce9c7b88767f6Yuichi Araki boolean offsetY = false; 13406206ad57276146c8f70e939fd40ce9c7b88767f6Yuichi Araki if ((absDodgeInsetEdges & Gravity.TOP) == Gravity.TOP) { 13416206ad57276146c8f70e939fd40ce9c7b88767f6Yuichi Araki int distance = rect.top - lp.topMargin - lp.mInsetOffsetY; 13426206ad57276146c8f70e939fd40ce9c7b88767f6Yuichi Araki if (distance < inset.top) { 13436206ad57276146c8f70e939fd40ce9c7b88767f6Yuichi Araki setInsetOffsetY(child, inset.top - distance); 13446206ad57276146c8f70e939fd40ce9c7b88767f6Yuichi Araki offsetY = true; 1345943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki } 13466206ad57276146c8f70e939fd40ce9c7b88767f6Yuichi Araki } 13476206ad57276146c8f70e939fd40ce9c7b88767f6Yuichi Araki if ((absDodgeInsetEdges & Gravity.BOTTOM) == Gravity.BOTTOM) { 13486206ad57276146c8f70e939fd40ce9c7b88767f6Yuichi Araki int distance = getHeight() - rect.bottom - lp.bottomMargin + lp.mInsetOffsetY; 13496206ad57276146c8f70e939fd40ce9c7b88767f6Yuichi Araki if (distance < inset.bottom) { 13506206ad57276146c8f70e939fd40ce9c7b88767f6Yuichi Araki setInsetOffsetY(child, distance - inset.bottom); 13516206ad57276146c8f70e939fd40ce9c7b88767f6Yuichi Araki offsetY = true; 1352943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki } 1353943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki } 13546206ad57276146c8f70e939fd40ce9c7b88767f6Yuichi Araki if (!offsetY) { 13556206ad57276146c8f70e939fd40ce9c7b88767f6Yuichi Araki setInsetOffsetY(child, 0); 13566206ad57276146c8f70e939fd40ce9c7b88767f6Yuichi Araki } 135726c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes 13586206ad57276146c8f70e939fd40ce9c7b88767f6Yuichi Araki boolean offsetX = false; 13596206ad57276146c8f70e939fd40ce9c7b88767f6Yuichi Araki if ((absDodgeInsetEdges & Gravity.LEFT) == Gravity.LEFT) { 13606206ad57276146c8f70e939fd40ce9c7b88767f6Yuichi Araki int distance = rect.left - lp.leftMargin - lp.mInsetOffsetX; 13616206ad57276146c8f70e939fd40ce9c7b88767f6Yuichi Araki if (distance < inset.left) { 13626206ad57276146c8f70e939fd40ce9c7b88767f6Yuichi Araki setInsetOffsetX(child, inset.left - distance); 13636206ad57276146c8f70e939fd40ce9c7b88767f6Yuichi Araki offsetX = true; 136426c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes } 13656206ad57276146c8f70e939fd40ce9c7b88767f6Yuichi Araki } 13666206ad57276146c8f70e939fd40ce9c7b88767f6Yuichi Araki if ((absDodgeInsetEdges & Gravity.RIGHT) == Gravity.RIGHT) { 13676206ad57276146c8f70e939fd40ce9c7b88767f6Yuichi Araki int distance = getWidth() - rect.right - lp.rightMargin + lp.mInsetOffsetX; 13686206ad57276146c8f70e939fd40ce9c7b88767f6Yuichi Araki if (distance < inset.right) { 13696206ad57276146c8f70e939fd40ce9c7b88767f6Yuichi Araki setInsetOffsetX(child, distance - inset.right); 13706206ad57276146c8f70e939fd40ce9c7b88767f6Yuichi Araki offsetX = true; 1371943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki } 1372943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki } 13736206ad57276146c8f70e939fd40ce9c7b88767f6Yuichi Araki if (!offsetX) { 13746206ad57276146c8f70e939fd40ce9c7b88767f6Yuichi Araki setInsetOffsetX(child, 0); 13756206ad57276146c8f70e939fd40ce9c7b88767f6Yuichi Araki } 1376943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki } 1377943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki 1378943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki private void setInsetOffsetX(View child, int offsetX) { 1379943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 1380943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki if (lp.mInsetOffsetX != offsetX) { 1381943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki final int dx = offsetX - lp.mInsetOffsetX; 1382943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki ViewCompat.offsetLeftAndRight(child, dx); 1383943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki lp.mInsetOffsetX = offsetX; 1384943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki } 1385943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki } 1386943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki 1387943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki private void setInsetOffsetY(View child, int offsetY) { 1388943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 1389943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki if (lp.mInsetOffsetY != offsetY) { 1390943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki final int dy = offsetY - lp.mInsetOffsetY; 1391943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki ViewCompat.offsetTopAndBottom(child, dy); 1392943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki lp.mInsetOffsetY = offsetY; 1393943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki } 1394943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki } 1395943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki 1396a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes /** 1397a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * Allows the caller to manually dispatch 1398a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * {@link Behavior#onDependentViewChanged(CoordinatorLayout, View, View)} to the associated 1399a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * {@link Behavior} instances of views which depend on the provided {@link View}. 1400a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * 1401a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * <p>You should not normally need to call this method as the it will be automatically done 1402a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * when the view has changed. 1403a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * 1404a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * @param view the View to find dependents of to dispatch the call. 1405a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes */ 1406a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes public void dispatchDependentViewsChanged(View view) { 1407a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes final List<View> dependents = mChildDag.getIncomingEdges(view); 1408a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes if (dependents != null && !dependents.isEmpty()) { 1409a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes for (int i = 0; i < dependents.size(); i++) { 14102f517207503fdffbcf930584a37b4a03392755d6Chris Banes final View child = dependents.get(i); 1411a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams) 1412a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes child.getLayoutParams(); 1413a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes CoordinatorLayout.Behavior b = lp.getBehavior(); 1414a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes if (b != null) { 1415a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes b.onDependentViewChanged(this, child, view); 1416a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1417a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1418a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1419a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1420a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1421a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1422a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes * Returns the list of views which the provided view depends on. Do not store this list as its 1423a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * contents may not be valid beyond the caller. 1424a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * 1425a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * @param child the view to find dependencies for. 1426a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * 1427a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * @return the list of views which {@code child} depends on. 1428a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes */ 1429c07c8e1e74a026c0d9e3a9dd119913436380be38Chris Banes @NonNull 1430a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes public List<View> getDependencies(@NonNull View child) { 1431a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes final List<View> dependencies = mChildDag.getOutgoingEdges(child); 1432a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes mTempDependenciesList.clear(); 1433a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes if (dependencies != null) { 1434a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes mTempDependenciesList.addAll(dependencies); 1435a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes } 1436a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes return mTempDependenciesList; 1437a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes } 1438a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 1439a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes /** 1440a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes * Returns the list of views which depend on the provided view. Do not store this list as its 1441a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes * contents may not be valid beyond the caller. 1442a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes * 1443a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes * @param child the view to find dependents of. 1444a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes * 1445a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes * @return the list of views which depend on {@code child}. 1446a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes */ 1447c07c8e1e74a026c0d9e3a9dd119913436380be38Chris Banes @NonNull 1448a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes public List<View> getDependents(@NonNull View child) { 1449a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes final List<View> edges = mChildDag.getIncomingEdges(child); 1450a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes mTempDependenciesList.clear(); 1451a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes if (edges != null) { 1452a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes mTempDependenciesList.addAll(edges); 1453a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1454a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes return mTempDependenciesList; 1455a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes } 1456a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 1457a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes @VisibleForTesting 1458a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes final List<View> getDependencySortedChildren() { 14592f517207503fdffbcf930584a37b4a03392755d6Chris Banes prepareChildren(); 1460a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes return Collections.unmodifiableList(mDependencySortedChildren); 1461a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1462a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 1463a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes /** 1464a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Add or remove the pre-draw listener as necessary. 1465a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1466a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void ensurePreDrawListener() { 1467a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean hasDependencies = false; 1468a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int childCount = getChildCount(); 1469a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (int i = 0; i < childCount; i++) { 1470a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final View child = getChildAt(i); 1471a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (hasDependencies(child)) { 1472a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell hasDependencies = true; 1473a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell break; 1474a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1475a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1476a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1477a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (hasDependencies != mNeedsPreDrawListener) { 1478a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (hasDependencies) { 1479a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell addPreDrawListener(); 1480a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else { 1481a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell removePreDrawListener(); 1482a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1483a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1484a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1485a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1486a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1487a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Check if the given child has any layout dependencies on other child views. 1488a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 14892f517207503fdffbcf930584a37b4a03392755d6Chris Banes private boolean hasDependencies(View child) { 1490a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes return mChildDag.hasOutgoingEdges(child); 1491a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1492a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1493a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1494a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Add the pre-draw listener if we're attached to a window and mark that we currently 1495a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * need it when attached. 1496a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1497a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void addPreDrawListener() { 1498a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mIsAttachedToWindow) { 1499a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Add the listener 1500a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mOnPreDrawListener == null) { 1501a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mOnPreDrawListener = new OnPreDrawListener(); 1502a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1503a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final ViewTreeObserver vto = getViewTreeObserver(); 1504a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell vto.addOnPreDrawListener(mOnPreDrawListener); 1505a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1506a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1507a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Record that we need the listener regardless of whether or not we're attached. 1508a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // We'll add the real listener when we become attached. 1509a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mNeedsPreDrawListener = true; 1510a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1511a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1512a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1513a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Remove the pre-draw listener if we're attached to a window and mark that we currently 1514a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * do not need it when attached. 1515a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1516a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void removePreDrawListener() { 1517a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mIsAttachedToWindow) { 1518a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mOnPreDrawListener != null) { 1519a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final ViewTreeObserver vto = getViewTreeObserver(); 1520a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell vto.removeOnPreDrawListener(mOnPreDrawListener); 1521a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1522a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1523a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mNeedsPreDrawListener = false; 1524a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1525a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1526a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1527a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Adjust the child left, top, right, bottom rect to the correct anchor view position, 1528a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * respecting gravity and anchor gravity. 1529a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1530a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Note that child translation properties are ignored in this process, allowing children 1531a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * to be animated away from their anchor. However, if the anchor view is animated, 1532a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * the child will be offset to match the anchor's translated position. 1533a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1534a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void offsetChildToAnchor(View child, int layoutDirection) { 1535a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 1536a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (lp.mAnchorView != null) { 1537a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Rect anchorRect = mTempRect1; 1538a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Rect childRect = mTempRect2; 1539a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Rect desiredChildRect = mTempRect3; 1540a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1541a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getDescendantRect(lp.mAnchorView, anchorRect); 1542a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getChildRect(child, false, childRect); 15438f8034a4204fc10c4805758051f0cec2159c0e40Yuichi Araki 15448f8034a4204fc10c4805758051f0cec2159c0e40Yuichi Araki int childWidth = child.getMeasuredWidth(); 15458f8034a4204fc10c4805758051f0cec2159c0e40Yuichi Araki int childHeight = child.getMeasuredHeight(); 15468f8034a4204fc10c4805758051f0cec2159c0e40Yuichi Araki getDesiredAnchoredChildRectWithoutConstraints(child, layoutDirection, anchorRect, 15478f8034a4204fc10c4805758051f0cec2159c0e40Yuichi Araki desiredChildRect, lp, childWidth, childHeight); 15488f8034a4204fc10c4805758051f0cec2159c0e40Yuichi Araki boolean changed = desiredChildRect.left != childRect.left || 15498f8034a4204fc10c4805758051f0cec2159c0e40Yuichi Araki desiredChildRect.top != childRect.top; 15508f8034a4204fc10c4805758051f0cec2159c0e40Yuichi Araki constrainChildRect(lp, desiredChildRect, childWidth, childHeight); 1551a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1552a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int dx = desiredChildRect.left - childRect.left; 1553a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final int dy = desiredChildRect.top - childRect.top; 1554a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1555a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (dx != 0) { 1556a5c36708f8dd136f2a02a79709923630449be5b5Chris Banes ViewCompat.offsetLeftAndRight(child, dx); 1557a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1558a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (dy != 0) { 1559a5c36708f8dd136f2a02a79709923630449be5b5Chris Banes ViewCompat.offsetTopAndBottom(child, dy); 1560a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1561a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 15628f8034a4204fc10c4805758051f0cec2159c0e40Yuichi Araki if (changed) { 1563a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes // If we have needed to move, make sure to notify the child's Behavior 1564a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes final Behavior b = lp.getBehavior(); 1565a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes if (b != null) { 1566a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes b.onDependentViewChanged(this, child, lp.mAnchorView); 1567a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1568a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1569a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1570a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1571a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1572a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1573a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Check if a given point in the CoordinatorLayout's coordinates are within the view bounds 1574a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * of the given direct child view. 1575a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1576a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child view to test 1577a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param x X coordinate to test, in the CoordinatorLayout's coordinate system 1578a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param y Y coordinate to test, in the CoordinatorLayout's coordinate system 1579a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true if the point is within the child view's bounds, false otherwise 1580a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1581a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean isPointInChildBounds(View child, int x, int y) { 1582a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Rect r = mTempRect1; 1583a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell getDescendantRect(child, r); 1584a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return r.contains(x, y); 1585a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1586a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1587b7f9224b1495db47eb8fd813b5912250e900770aChris Banes /** 1588b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * Check whether two views overlap each other. The views need to be descendants of this 1589b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * {@link CoordinatorLayout} in the view hierarchy. 1590b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * 1591b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * @param first first child view to test 1592b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * @param second second child view to test 1593b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * @return true if both views are visible and overlap each other 1594b7f9224b1495db47eb8fd813b5912250e900770aChris Banes */ 1595b7f9224b1495db47eb8fd813b5912250e900770aChris Banes public boolean doViewsOverlap(View first, View second) { 1596b7f9224b1495db47eb8fd813b5912250e900770aChris Banes if (first.getVisibility() == VISIBLE && second.getVisibility() == VISIBLE) { 1597b7f9224b1495db47eb8fd813b5912250e900770aChris Banes final Rect firstRect = mTempRect1; 1598b7f9224b1495db47eb8fd813b5912250e900770aChris Banes getChildRect(first, first.getParent() != this, firstRect); 1599b7f9224b1495db47eb8fd813b5912250e900770aChris Banes final Rect secondRect = mTempRect2; 1600b7f9224b1495db47eb8fd813b5912250e900770aChris Banes getChildRect(second, second.getParent() != this, secondRect); 1601b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 1602b7f9224b1495db47eb8fd813b5912250e900770aChris Banes return !(firstRect.left > secondRect.right || firstRect.top > secondRect.bottom 1603b7f9224b1495db47eb8fd813b5912250e900770aChris Banes || firstRect.right < secondRect.left || firstRect.bottom < secondRect.top); 1604b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 1605b7f9224b1495db47eb8fd813b5912250e900770aChris Banes return false; 1606b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 1607b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 1608a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 1609a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public LayoutParams generateLayoutParams(AttributeSet attrs) { 1610a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return new LayoutParams(getContext(), attrs); 1611a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1612a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1613a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 1614a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { 1615a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (p instanceof LayoutParams) { 1616a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return new LayoutParams((LayoutParams) p); 1617a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else if (p instanceof MarginLayoutParams) { 1618a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return new LayoutParams((MarginLayoutParams) p); 1619a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1620a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return new LayoutParams(p); 1621a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1622a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1623a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 1624a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell protected LayoutParams generateDefaultLayoutParams() { 1625a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); 1626a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1627a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1628a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 1629a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { 1630a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return p instanceof LayoutParams && super.checkLayoutParams(p); 1631a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1632a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 163315375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas @Override 1634a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) { 16355cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell boolean handled = false; 16365cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 16375cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final int childCount = getChildCount(); 16385cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell for (int i = 0; i < childCount; i++) { 16395cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final View view = getChildAt(i); 16405cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final LayoutParams lp = (LayoutParams) view.getLayoutParams(); 16415cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final Behavior viewBehavior = lp.getBehavior(); 16425cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (viewBehavior != null) { 16435cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final boolean accepted = viewBehavior.onStartNestedScroll(this, view, child, target, 16445cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell nestedScrollAxes); 16455cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell handled |= accepted; 16465cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 16475cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell lp.acceptNestedScroll(accepted); 16485cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } else { 16495cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell lp.acceptNestedScroll(false); 16505cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 16515cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 16525cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell return handled; 1653a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1654a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 165515375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas @Override 1656a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public void onNestedScrollAccepted(View child, View target, int nestedScrollAxes) { 1657a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mNestedScrollingParentHelper.onNestedScrollAccepted(child, target, nestedScrollAxes); 16585cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell mNestedScrollingDirectChild = child; 16595cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell mNestedScrollingTarget = target; 16605cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 16615cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final int childCount = getChildCount(); 16625cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell for (int i = 0; i < childCount; i++) { 16635cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final View view = getChildAt(i); 16645cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final LayoutParams lp = (LayoutParams) view.getLayoutParams(); 16655cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (!lp.isNestedScrollAccepted()) { 16665cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell continue; 16675cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 16685cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 16695cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final Behavior viewBehavior = lp.getBehavior(); 16705cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (viewBehavior != null) { 16715cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell viewBehavior.onNestedScrollAccepted(this, view, child, target, nestedScrollAxes); 16725cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 16735cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 1674a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1675a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 167615375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas @Override 1677a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public void onStopNestedScroll(View target) { 1678a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mNestedScrollingParentHelper.onStopNestedScroll(target); 16795cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 16805cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final int childCount = getChildCount(); 16815cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell for (int i = 0; i < childCount; i++) { 16825cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final View view = getChildAt(i); 16835cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final LayoutParams lp = (LayoutParams) view.getLayoutParams(); 16845cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (!lp.isNestedScrollAccepted()) { 16855cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell continue; 16865cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 16875cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 16885cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final Behavior viewBehavior = lp.getBehavior(); 16895cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (viewBehavior != null) { 16905cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell viewBehavior.onStopNestedScroll(this, view, target); 16915cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 16925cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell lp.resetNestedScroll(); 1693a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes lp.resetChangedAfterNestedScroll(); 16945cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 16955cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 16965cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell mNestedScrollingDirectChild = null; 16975cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell mNestedScrollingTarget = null; 1698a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1699a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 170015375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas @Override 1701a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public void onNestedScroll(View target, int dxConsumed, int dyConsumed, 1702a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int dxUnconsumed, int dyUnconsumed) { 17035cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final int childCount = getChildCount(); 1704a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes boolean accepted = false; 1705a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 17065cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell for (int i = 0; i < childCount; i++) { 17075cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final View view = getChildAt(i); 17085cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final LayoutParams lp = (LayoutParams) view.getLayoutParams(); 17095cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (!lp.isNestedScrollAccepted()) { 17105cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell continue; 17115cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 17125cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 17135cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final Behavior viewBehavior = lp.getBehavior(); 17145cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (viewBehavior != null) { 17155cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell viewBehavior.onNestedScroll(this, view, target, dxConsumed, dyConsumed, 17165cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell dxUnconsumed, dyUnconsumed); 1717a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes accepted = true; 17185cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 17195cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 1720a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 1721a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes if (accepted) { 172226c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes onChildViewsChanged(EVENT_NESTED_SCROLL); 1723a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1724a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1725a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 172615375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas @Override 1727a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) { 17285cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell int xConsumed = 0; 17295cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell int yConsumed = 0; 1730a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes boolean accepted = false; 17315cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 17325cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final int childCount = getChildCount(); 17335cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell for (int i = 0; i < childCount; i++) { 17345cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final View view = getChildAt(i); 17355cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final LayoutParams lp = (LayoutParams) view.getLayoutParams(); 17365cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (!lp.isNestedScrollAccepted()) { 17375cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell continue; 17385cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 17395cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 17405cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final Behavior viewBehavior = lp.getBehavior(); 17415cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (viewBehavior != null) { 17425cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell mTempIntPair[0] = mTempIntPair[1] = 0; 17435cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell viewBehavior.onNestedPreScroll(this, view, target, dx, dy, mTempIntPair); 17445cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 17455cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell xConsumed = dx > 0 ? Math.max(xConsumed, mTempIntPair[0]) 17465cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell : Math.min(xConsumed, mTempIntPair[0]); 17475cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell yConsumed = dy > 0 ? Math.max(yConsumed, mTempIntPair[1]) 17485cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell : Math.min(yConsumed, mTempIntPair[1]); 1749a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 1750a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes accepted = true; 17515cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 17525cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 17535cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 17545cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell consumed[0] = xConsumed; 17555cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell consumed[1] = yConsumed; 1756a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 1757a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes if (accepted) { 175826c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes onChildViewsChanged(EVENT_NESTED_SCROLL); 1759a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 1760a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1761a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 176215375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas @Override 1763a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) { 17645cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell boolean handled = false; 17655cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 17665cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final int childCount = getChildCount(); 17675cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell for (int i = 0; i < childCount; i++) { 17685cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final View view = getChildAt(i); 17695cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final LayoutParams lp = (LayoutParams) view.getLayoutParams(); 17705cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (!lp.isNestedScrollAccepted()) { 17715cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell continue; 17725cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 17735cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 17745cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final Behavior viewBehavior = lp.getBehavior(); 17755cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (viewBehavior != null) { 17765cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell handled |= viewBehavior.onNestedFling(this, view, target, velocityX, velocityY, 17775cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell consumed); 17785cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 17795cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 1780a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes if (handled) { 178126c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes onChildViewsChanged(EVENT_NESTED_SCROLL); 1782a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 17835cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell return handled; 1784a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1785a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 178615375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas @Override 1787a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean onNestedPreFling(View target, float velocityX, float velocityY) { 17885cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell boolean handled = false; 17895cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 17905cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final int childCount = getChildCount(); 17915cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell for (int i = 0; i < childCount; i++) { 17925cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final View view = getChildAt(i); 17935cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final LayoutParams lp = (LayoutParams) view.getLayoutParams(); 17945cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (!lp.isNestedScrollAccepted()) { 17955cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell continue; 17965cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 17975cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 17985cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell final Behavior viewBehavior = lp.getBehavior(); 17995cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell if (viewBehavior != null) { 18005cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell handled |= viewBehavior.onNestedPreFling(this, view, target, velocityX, velocityY); 18015cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 18025cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 18035cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell return handled; 1804a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1805a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 180615375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas @Override 1807a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public int getNestedScrollAxes() { 1808a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return mNestedScrollingParentHelper.getNestedScrollAxes(); 1809a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1810a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1811a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell class OnPreDrawListener implements ViewTreeObserver.OnPreDrawListener { 1812a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 1813a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean onPreDraw() { 181426c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes onChildViewsChanged(EVENT_PRE_DRAW); 1815a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return true; 1816a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1817a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1818a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1819a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1820a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Sorts child views with higher Z values to the beginning of a collection. 1821a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1822a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell static class ViewElevationComparator implements Comparator<View> { 1823a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Override 1824a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public int compare(View lhs, View rhs) { 1825a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final float lz = ViewCompat.getZ(lhs); 1826a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final float rz = ViewCompat.getZ(rhs); 1827a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (lz > rz) { 1828a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return -1; 1829a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else if (lz < rz) { 1830a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return 1; 1831a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1832a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return 0; 1833a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1834a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1835a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1836a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1837a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Defines the default {@link Behavior} of a {@link View} class. 1838a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1839a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>When writing a custom view, use this annotation to define the default behavior 1840a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * when used as a direct child of an {@link CoordinatorLayout}. The default behavior 1841a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * can be overridden using {@link LayoutParams#setBehavior}.</p> 1842a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1843a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>Example: <code>@DefaultBehavior(MyBehavior.class)</code></p> 1844a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1845a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell @Retention(RetentionPolicy.RUNTIME) 1846a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public @interface DefaultBehavior { 1847a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Class<? extends Behavior> value(); 1848a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1849a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1850a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1851a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Interaction behavior plugin for child views of {@link CoordinatorLayout}. 1852a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1853a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>A Behavior implements one or more interactions that a user can take on a child view. 1854a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * These interactions may include drags, swipes, flings, or any other gestures.</p> 1855a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1856a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param <V> The View type that this Behavior operates on 1857a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1858a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public static abstract class Behavior<V extends View> { 1859a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1860a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1861a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Default constructor for instantiating Behaviors. 1862a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1863a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public Behavior() { 1864a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1865a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1866a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1867a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Default constructor for inflating Behaviors from layout. The Behavior will have 1868a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * the opportunity to parse specially defined layout parameters. These parameters will 1869a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * appear on the child view tag. 1870a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1871a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param context 1872a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param attrs 1873a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1874a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public Behavior(Context context, AttributeSet attrs) { 1875a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1876a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1877a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 187826c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes * Called when the Behavior has been attached to a LayoutParams instance. 187926c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes * 188026c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes * <p>This will be called after the LayoutParams has been instantiated and can be 188126c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes * modified.</p> 188226c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes * 188326c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes * @param params the LayoutParams instance that this Behavior has been attached to 188426c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes */ 188526c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes public void onAttachedToLayoutParams(@NonNull CoordinatorLayout.LayoutParams params) { 188626c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes } 188726c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes 188826c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes /** 188926c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes * Called when the Behavior has been detached from its holding LayoutParams instance. 189026c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes * 189126c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes * <p>This will only be called if the Behavior has been explicitly removed from the 189226c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes * LayoutParams instance via {@link LayoutParams#setBehavior(Behavior)}. It will not be 189326c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes * called if the associated view is removed from the CoordinatorLayout or similar.</p> 189426c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes */ 189526c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes public void onDetachedFromLayoutParams() { 189626c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes } 189726c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes 189826c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes /** 1899a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Respond to CoordinatorLayout touch events before they are dispatched to child views. 1900a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1901a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>Behaviors can use this to monitor inbound touch events until one decides to 1902a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * intercept the rest of the event stream to take an action on its associated child view. 1903a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * This method will return false until it detects the proper intercept conditions, then 1904a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * return true once those conditions have occurred.</p> 1905a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1906a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>Once a Behavior intercepts touch events, the rest of the event stream will 1907a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * be sent to the {@link #onTouchEvent} method.</p> 1908a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1909a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>The default implementation of this method always returns false.</p> 1910a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1911a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent view currently receiving this touch event 1912a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child view associated with this Behavior 1913a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param ev the MotionEvent describing the touch event being processed 1914a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true if this Behavior would like to intercept and take over the event stream. 1915a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * The default always returns false. 1916a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1917a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean onInterceptTouchEvent(CoordinatorLayout parent, V child, MotionEvent ev) { 1918a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return false; 1919a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1920a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1921a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1922a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Respond to CoordinatorLayout touch events after this Behavior has started 1923a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link #onInterceptTouchEvent intercepting} them. 1924a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1925a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>Behaviors may intercept touch events in order to help the CoordinatorLayout 1926a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * manipulate its child views. For example, a Behavior may allow a user to drag a 1927a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * UI pane open or closed. This method should perform actual mutations of view 1928a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * layout state.</p> 1929a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1930a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent view currently receiving this touch event 1931a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child view associated with this Behavior 1932a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param ev the MotionEvent describing the touch event being processed 1933a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true if this Behavior handled this touch event and would like to continue 1934a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * receiving events in this stream. The default always returns false. 1935a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1936a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean onTouchEvent(CoordinatorLayout parent, V child, MotionEvent ev) { 1937a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return false; 1938a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1939a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1940a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1941a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Supply a scrim color that will be painted behind the associated child view. 1942a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1943a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>A scrim may be used to indicate that the other elements beneath it are not currently 1944a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * interactive or actionable, drawing user focus and attention to the views above the scrim. 1945a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * </p> 1946a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1947a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>The default implementation returns {@link Color#BLACK}.</p> 1948a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1949a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent view of the given child 1950a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child view above the scrim 1951a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return the desired scrim color in 0xAARRGGBB format. The default return value is 1952a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link Color#BLACK}. 1953a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @see #getScrimOpacity(CoordinatorLayout, android.view.View) 1954a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1955b806673aa0977685995be820981207f6bf51858bChris Banes @ColorInt 19564d4b8a2a5b5907383e7ca168dd01c76dc75ab930Adam Powell public int getScrimColor(CoordinatorLayout parent, V child) { 1957a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return Color.BLACK; 1958a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1959a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1960a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1961a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Determine the current opacity of the scrim behind a given child view 1962a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1963a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>A scrim may be used to indicate that the other elements beneath it are not currently 1964a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * interactive or actionable, drawing user focus and attention to the views above the scrim. 1965a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * </p> 1966a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1967a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>The default implementation returns 0.0f.</p> 1968a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1969a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent view of the given child 1970a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child view above the scrim 1971a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return the desired scrim opacity from 0.0f to 1.0f. The default return value is 0.0f. 1972a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1973b806673aa0977685995be820981207f6bf51858bChris Banes @FloatRange(from = 0, to = 1) 19744d4b8a2a5b5907383e7ca168dd01c76dc75ab930Adam Powell public float getScrimOpacity(CoordinatorLayout parent, V child) { 1975a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return 0.f; 1976a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1977a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1978a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1979a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Determine whether interaction with views behind the given child in the child order 1980a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * should be blocked. 1981a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1982a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>The default implementation returns true if 1983a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link #getScrimOpacity(CoordinatorLayout, android.view.View)} would return > 0.0f.</p> 1984a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1985a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent view of the given child 1986a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child view to test 1987a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true if {@link #getScrimOpacity(CoordinatorLayout, android.view.View)} would 1988a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * return > 0.0f. 1989a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 1990a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean blocksInteractionBelow(CoordinatorLayout parent, V child) { 1991a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return getScrimOpacity(parent, child) > 0.f; 1992a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 1993a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 1994a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 1995a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Determine whether the supplied child view has another specific sibling view as a 1996a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * layout dependency. 1997a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 1998a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>This method will be called at least once in response to a layout request. If it 1999a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * returns true for a given child and dependency view pair, the parent CoordinatorLayout 2000a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * will:</p> 2001a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <ol> 2002a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <li>Always lay out this child after the dependent child is laid out, regardless 2003a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * of child order.</li> 2004a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <li>Call {@link #onDependentViewChanged} when the dependency view's layout or 2005a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * position changes.</li> 2006a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * </ol> 2007a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2008a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent view of the given child 2009a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child view to test 2010a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param dependency the proposed dependency of child 2011a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true if child's layout depends on the proposed dependency's layout, 2012a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * false otherwise 2013a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2014a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @see #onDependentViewChanged(CoordinatorLayout, android.view.View, android.view.View) 2015a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2016a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean layoutDependsOn(CoordinatorLayout parent, V child, View dependency) { 2017a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return false; 2018a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2019a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2020a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2021a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * Respond to a change in a child's dependent view 2022a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * 2023a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * <p>This method is called whenever a dependent view changes in size or position outside 2024a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * of the standard layout flow. A Behavior may use this method to appropriately update 2025a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * the child view in response.</p> 2026a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2027a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * <p>A view's dependency is determined by 2028a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * {@link #layoutDependsOn(CoordinatorLayout, android.view.View, android.view.View)} or 2029a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes * if {@code child} has set another view as it's anchor.</p> 2030a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2031a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>Note that if a Behavior changes the layout of a child via this method, it should 2032a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * also be able to reconstruct the correct position in 2033a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link #onLayoutChild(CoordinatorLayout, android.view.View, int) onLayoutChild}. 2034a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <code>onDependentViewChanged</code> will not be called during normal layout since 2035a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * the layout of each child view will always happen in dependency order.</p> 2036a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2037a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>If the Behavior changes the child view's size or position, it should return true. 2038a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * The default implementation returns false.</p> 2039a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2040a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent view of the given child 2041a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child view to manipulate 2042a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param dependency the dependent view that changed 2043a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true if the Behavior changed the child view's size or position, false otherwise 2044a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2045a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean onDependentViewChanged(CoordinatorLayout parent, V child, View dependency) { 2046a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return false; 2047a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2048a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2049a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 20500b00489086b22c9688c8c04990dadf54489d45e3Chris Banes * Respond to a child's dependent view being removed. 20510b00489086b22c9688c8c04990dadf54489d45e3Chris Banes * 20520b00489086b22c9688c8c04990dadf54489d45e3Chris Banes * <p>This method is called after a dependent view has been removed from the parent. 20530b00489086b22c9688c8c04990dadf54489d45e3Chris Banes * A Behavior may use this method to appropriately update the child view in response.</p> 20540b00489086b22c9688c8c04990dadf54489d45e3Chris Banes * 20550b00489086b22c9688c8c04990dadf54489d45e3Chris Banes * <p>A view's dependency is determined by 20560b00489086b22c9688c8c04990dadf54489d45e3Chris Banes * {@link #layoutDependsOn(CoordinatorLayout, android.view.View, android.view.View)} or 20570b00489086b22c9688c8c04990dadf54489d45e3Chris Banes * if {@code child} has set another view as it's anchor.</p> 20580b00489086b22c9688c8c04990dadf54489d45e3Chris Banes * 20590b00489086b22c9688c8c04990dadf54489d45e3Chris Banes * @param parent the parent view of the given child 20600b00489086b22c9688c8c04990dadf54489d45e3Chris Banes * @param child the child view to manipulate 20610b00489086b22c9688c8c04990dadf54489d45e3Chris Banes * @param dependency the dependent view that has been removed 20620b00489086b22c9688c8c04990dadf54489d45e3Chris Banes */ 20630b00489086b22c9688c8c04990dadf54489d45e3Chris Banes public void onDependentViewRemoved(CoordinatorLayout parent, V child, View dependency) { 20640b00489086b22c9688c8c04990dadf54489d45e3Chris Banes } 20650b00489086b22c9688c8c04990dadf54489d45e3Chris Banes 20660b00489086b22c9688c8c04990dadf54489d45e3Chris Banes /** 20675f9a5463fba574d8b33fd757b3e78b2b3613cb82Chris Banes * @deprecated this method is not called anymore. You can safely remove all usages 20684cf1d92509224fab3ca69b419a005c536ab75c5cChris Banes * and implementations. This method will be removed in a future release. 2069a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 20705f9a5463fba574d8b33fd757b3e78b2b3613cb82Chris Banes @Deprecated 2071a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean isDirty(CoordinatorLayout parent, V child) { 2072a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return false; 2073a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2074a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2075a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2076a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Called when the parent CoordinatorLayout is about to measure the given child view. 2077a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2078a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>This method can be used to perform custom or modified measurement of a child view 2079a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * in place of the default child measurement behavior. The Behavior's implementation 2080a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * can delegate to the standard CoordinatorLayout measurement behavior by calling 2081a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link CoordinatorLayout#onMeasureChild(android.view.View, int, int, int, int) 2082a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * parent.onMeasureChild}.</p> 2083a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2084a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent CoordinatorLayout 2085a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child to measure 2086a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parentWidthMeasureSpec the width requirements for this view 2087a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param widthUsed extra space that has been used up by the parent 2088a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * horizontally (possibly by other children of the parent) 2089a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parentHeightMeasureSpec the height requirements for this view 2090a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param heightUsed extra space that has been used up by the parent 2091a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * vertically (possibly by other children of the parent) 2092a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true if the Behavior measured the child view, false if the CoordinatorLayout 2093a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * should perform its default measurement 2094a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2095a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean onMeasureChild(CoordinatorLayout parent, V child, 2096a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int parentWidthMeasureSpec, int widthUsed, 2097a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int parentHeightMeasureSpec, int heightUsed) { 2098a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return false; 2099a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2100a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2101a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2102a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Called when the parent CoordinatorLayout is about the lay out the given child view. 2103a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2104a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>This method can be used to perform custom or modified layout of a child view 2105a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * in place of the default child layout behavior. The Behavior's implementation can 2106a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * delegate to the standard CoordinatorLayout measurement behavior by calling 2107a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link CoordinatorLayout#onLayoutChild(android.view.View, int) 2108c6d62e6d5ca277d4649c686e76edd63176c7c4e3Chris Banes * parent.onLayoutChild}.</p> 2109a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2110a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>If a Behavior implements 2111a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link #onDependentViewChanged(CoordinatorLayout, android.view.View, android.view.View)} 2112a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * to change the position of a view in response to a dependent view changing, it 2113a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * should also implement <code>onLayoutChild</code> in such a way that respects those 2114a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * dependent views. <code>onLayoutChild</code> will always be called for a dependent view 2115a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <em>after</em> its dependency has been laid out.</p> 2116a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2117a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent CoordinatorLayout 2118a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child view to lay out 2119a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param layoutDirection the resolved layout direction for the CoordinatorLayout, such as 2120a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link ViewCompat#LAYOUT_DIRECTION_LTR} or 2121a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link ViewCompat#LAYOUT_DIRECTION_RTL}. 2122a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true if the Behavior performed layout of the child view, false to request 2123a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * default layout behavior 2124a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2125a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public boolean onLayoutChild(CoordinatorLayout parent, V child, int layoutDirection) { 2126a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return false; 2127a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2128a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2129a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell // Utility methods for accessing child-specific, behavior-modifiable properties. 2130a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2131a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2132a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Associate a Behavior-specific tag object with the given child view. 2133a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * This object will be stored with the child view's LayoutParams. 2134a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2135a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child view to set tag with 2136a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param tag tag object to set 2137a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2138a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public static void setTag(View child, Object tag) { 2139a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 2140a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell lp.mBehaviorTag = tag; 2141a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2142a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2143a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2144a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Get the behavior-specific tag object with the given child view. 2145a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * This object is stored with the child view's LayoutParams. 2146a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2147a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child child view to get tag with 2148a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return the previously stored tag object 2149a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2150a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public static Object getTag(View child) { 2151a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 2152a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return lp.mBehaviorTag; 2153a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 21545cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 21555cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 21565cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell /** 21575cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * Called when a descendant of the CoordinatorLayout attempts to initiate a nested scroll. 21585cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 21595cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p>Any Behavior associated with any direct child of the CoordinatorLayout may respond 21605cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * to this event and return true to indicate that the CoordinatorLayout should act as 21615cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * a nested scrolling parent for this scroll. Only Behaviors that return true from 21625cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * this method will receive subsequent nested scroll events.</p> 21635cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 21645cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is 21655cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * associated with 21665cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param child the child view of the CoordinatorLayout this Behavior is associated with 21675cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param directTargetChild the child view of the CoordinatorLayout that either is or 21685cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * contains the target of the nested scroll operation 21695cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param target the descendant view of the CoordinatorLayout initiating the nested scroll 21705cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param nestedScrollAxes the axes that this nested scroll applies to. See 21715cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * {@link ViewCompat#SCROLL_AXIS_HORIZONTAL}, 21725cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * {@link ViewCompat#SCROLL_AXIS_VERTICAL} 21735cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @return true if the Behavior wishes to accept this nested scroll 21745cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 21755cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @see NestedScrollingParent#onStartNestedScroll(View, View, int) 21765cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell */ 21775cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, 21785cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell V child, View directTargetChild, View target, int nestedScrollAxes) { 21795cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell return false; 21805cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 21815cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 21825cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell /** 21835cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * Called when a nested scroll has been accepted by the CoordinatorLayout. 21845cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 21855cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p>Any Behavior associated with any direct child of the CoordinatorLayout may elect 21865cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * to accept the nested scroll as part of {@link #onStartNestedScroll}. Each Behavior 21875cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * that returned true will receive subsequent nested scroll events for that nested scroll. 21885cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * </p> 21895cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 21905cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is 21915cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * associated with 21925cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param child the child view of the CoordinatorLayout this Behavior is associated with 21935cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param directTargetChild the child view of the CoordinatorLayout that either is or 21945cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * contains the target of the nested scroll operation 21955cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param target the descendant view of the CoordinatorLayout initiating the nested scroll 21965cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param nestedScrollAxes the axes that this nested scroll applies to. See 21975cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * {@link ViewCompat#SCROLL_AXIS_HORIZONTAL}, 21985cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * {@link ViewCompat#SCROLL_AXIS_VERTICAL} 21995cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 22005cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @see NestedScrollingParent#onNestedScrollAccepted(View, View, int) 22015cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell */ 22025cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell public void onNestedScrollAccepted(CoordinatorLayout coordinatorLayout, V child, 22035cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell View directTargetChild, View target, int nestedScrollAxes) { 22045cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell // Do nothing 22055cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 22065cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 22075cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell /** 22085cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * Called when a nested scroll has ended. 22095cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 22105cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p>Any Behavior associated with any direct child of the CoordinatorLayout may elect 22115cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * to accept the nested scroll as part of {@link #onStartNestedScroll}. Each Behavior 22125cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * that returned true will receive subsequent nested scroll events for that nested scroll. 22135cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * </p> 22145cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 22155cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p><code>onStopNestedScroll</code> marks the end of a single nested scroll event 22165cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * sequence. This is a good place to clean up any state related to the nested scroll. 22175cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * </p> 22185cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 22195cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is 22205cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * associated with 22215cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param child the child view of the CoordinatorLayout this Behavior is associated with 22225cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param target the descendant view of the CoordinatorLayout that initiated 22235cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * the nested scroll 22245cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 22255cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @see NestedScrollingParent#onStopNestedScroll(View) 22265cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell */ 22275cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, V child, View target) { 22285cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell // Do nothing 22295cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 22305cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 22315cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell /** 22325cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * Called when a nested scroll in progress has updated and the target has scrolled or 22335cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * attempted to scroll. 22345cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 22355cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p>Any Behavior associated with the direct child of the CoordinatorLayout may elect 22365cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * to accept the nested scroll as part of {@link #onStartNestedScroll}. Each Behavior 22375cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * that returned true will receive subsequent nested scroll events for that nested scroll. 22385cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * </p> 22395cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 22405cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p><code>onNestedScroll</code> is called each time the nested scroll is updated by the 22415cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * nested scrolling child, with both consumed and unconsumed components of the scroll 22425cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * supplied in pixels. <em>Each Behavior responding to the nested scroll will receive the 22435cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * same values.</em> 22445cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * </p> 22455cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 22465cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is 22475cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * associated with 22485cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param child the child view of the CoordinatorLayout this Behavior is associated with 22495cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param target the descendant view of the CoordinatorLayout performing the nested scroll 22505cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param dxConsumed horizontal pixels consumed by the target's own scrolling operation 22515cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param dyConsumed vertical pixels consumed by the target's own scrolling operation 22525cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param dxUnconsumed horizontal pixels not consumed by the target's own scrolling 22535cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * operation, but requested by the user 22545cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param dyUnconsumed vertical pixels not consumed by the target's own scrolling operation, 22555cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * but requested by the user 22565cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 22575cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @see NestedScrollingParent#onNestedScroll(View, int, int, int, int) 22585cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell */ 22595cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell public void onNestedScroll(CoordinatorLayout coordinatorLayout, V child, View target, 22605cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) { 22615cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell // Do nothing 22625cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 22635cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 22645cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell /** 22655cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * Called when a nested scroll in progress is about to update, before the target has 22665cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * consumed any of the scrolled distance. 22675cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 22685cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p>Any Behavior associated with the direct child of the CoordinatorLayout may elect 22695cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * to accept the nested scroll as part of {@link #onStartNestedScroll}. Each Behavior 22705cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * that returned true will receive subsequent nested scroll events for that nested scroll. 22715cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * </p> 22725cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 22735cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p><code>onNestedPreScroll</code> is called each time the nested scroll is updated 22745cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * by the nested scrolling child, before the nested scrolling child has consumed the scroll 22755cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * distance itself. <em>Each Behavior responding to the nested scroll will receive the 22765cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * same values.</em> The CoordinatorLayout will report as consumed the maximum number 22775cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * of pixels in either direction that any Behavior responding to the nested scroll reported 22785cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * as consumed.</p> 22795cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 22805cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is 22815cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * associated with 22825cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param child the child view of the CoordinatorLayout this Behavior is associated with 22835cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param target the descendant view of the CoordinatorLayout performing the nested scroll 22845cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param dx the raw horizontal number of pixels that the user attempted to scroll 22855cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param dy the raw vertical number of pixels that the user attempted to scroll 22865cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param consumed out parameter. consumed[0] should be set to the distance of dx that 22875cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * was consumed, consumed[1] should be set to the distance of dy that 22885cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * was consumed 22895cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 22905cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @see NestedScrollingParent#onNestedPreScroll(View, int, int, int[]) 22915cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell */ 22925cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, V child, View target, 22935cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell int dx, int dy, int[] consumed) { 22945cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell // Do nothing 22955cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 22965cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 22975cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell /** 22985cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * Called when a nested scrolling child is starting a fling or an action that would 22995cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * be a fling. 23005cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 23015cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p>Any Behavior associated with the direct child of the CoordinatorLayout may elect 23025cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * to accept the nested scroll as part of {@link #onStartNestedScroll}. Each Behavior 23035cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * that returned true will receive subsequent nested scroll events for that nested scroll. 23045cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * </p> 23055cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 23065cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p><code>onNestedFling</code> is called when the current nested scrolling child view 23075cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * detects the proper conditions for a fling. It reports if the child itself consumed 23085cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * the fling. If it did not, the child is expected to show some sort of overscroll 23095cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * indication. This method should return true if it consumes the fling, so that a child 23105cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * that did not itself take an action in response can choose not to show an overfling 23115cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * indication.</p> 23125cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 23135cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is 23145cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * associated with 23155cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param child the child view of the CoordinatorLayout this Behavior is associated with 23165cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param target the descendant view of the CoordinatorLayout performing the nested scroll 23175cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param velocityX horizontal velocity of the attempted fling 23185cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param velocityY vertical velocity of the attempted fling 23195cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param consumed true if the nested child view consumed the fling 23205cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @return true if the Behavior consumed the fling 23215cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 23225cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @see NestedScrollingParent#onNestedFling(View, float, float, boolean) 23235cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell */ 23245cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell public boolean onNestedFling(CoordinatorLayout coordinatorLayout, V child, View target, 23255cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell float velocityX, float velocityY, boolean consumed) { 23265cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell return false; 23275cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 23285cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 23295cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell /** 23305cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * Called when a nested scrolling child is about to start a fling. 23315cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 23325cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p>Any Behavior associated with the direct child of the CoordinatorLayout may elect 23335cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * to accept the nested scroll as part of {@link #onStartNestedScroll}. Each Behavior 23345cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * that returned true will receive subsequent nested scroll events for that nested scroll. 23355cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * </p> 23365cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 23375cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * <p><code>onNestedPreFling</code> is called when the current nested scrolling child view 23385cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * detects the proper conditions for a fling, but it has not acted on it yet. A 23395cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * Behavior can return true to indicate that it consumed the fling. If at least one 23405cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * Behavior returns true, the fling should not be acted upon by the child.</p> 23415cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 23425cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is 23435cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * associated with 23445cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param child the child view of the CoordinatorLayout this Behavior is associated with 23455cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param target the descendant view of the CoordinatorLayout performing the nested scroll 23465cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param velocityX horizontal velocity of the attempted fling 23475cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @param velocityY vertical velocity of the attempted fling 23485cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @return true if the Behavior consumed the fling 23495cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * 23505cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell * @see NestedScrollingParent#onNestedPreFling(View, float, float) 23515cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell */ 23525cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell public boolean onNestedPreFling(CoordinatorLayout coordinatorLayout, V child, View target, 23535cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell float velocityX, float velocityY) { 23545cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell return false; 23555cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 235675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 235775284fffafacd32f4d178020050589f9e70e5ed9Chris Banes /** 235875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * Called when the window insets have changed. 235975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * 236075284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * <p>Any Behavior associated with the direct child of the CoordinatorLayout may elect 236175284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * to handle the window inset change on behalf of it's associated view. 236275284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * </p> 236375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * 236475284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is 236575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * associated with 236675284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * @param child the child view of the CoordinatorLayout this Behavior is associated with 236775284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * @param insets the new window insets. 236875284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * 236975284fffafacd32f4d178020050589f9e70e5ed9Chris Banes * @return The insets supplied, minus any insets that were consumed 237075284fffafacd32f4d178020050589f9e70e5ed9Chris Banes */ 23713035e10317eb12c58153d8c651a791896ea3094eChris Banes @NonNull 237275284fffafacd32f4d178020050589f9e70e5ed9Chris Banes public WindowInsetsCompat onApplyWindowInsets(CoordinatorLayout coordinatorLayout, 237375284fffafacd32f4d178020050589f9e70e5ed9Chris Banes V child, WindowInsetsCompat insets) { 237475284fffafacd32f4d178020050589f9e70e5ed9Chris Banes return insets; 237575284fffafacd32f4d178020050589f9e70e5ed9Chris Banes } 2376e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2377e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes /** 237800a00a7d3ba8279294f63994473afc32e05dcf10Chris Banes * Called when a child of the view associated with this behavior wants a particular 237900a00a7d3ba8279294f63994473afc32e05dcf10Chris Banes * rectangle to be positioned onto the screen. 238000a00a7d3ba8279294f63994473afc32e05dcf10Chris Banes * 238100a00a7d3ba8279294f63994473afc32e05dcf10Chris Banes * <p>The contract for this method is the same as 238200a00a7d3ba8279294f63994473afc32e05dcf10Chris Banes * {@link ViewParent#requestChildRectangleOnScreen(View, Rect, boolean)}.</p> 238300a00a7d3ba8279294f63994473afc32e05dcf10Chris Banes * 238400a00a7d3ba8279294f63994473afc32e05dcf10Chris Banes * @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is 238500a00a7d3ba8279294f63994473afc32e05dcf10Chris Banes * associated with 238600a00a7d3ba8279294f63994473afc32e05dcf10Chris Banes * @param child the child view of the CoordinatorLayout this Behavior is 238700a00a7d3ba8279294f63994473afc32e05dcf10Chris Banes * associated with 238800a00a7d3ba8279294f63994473afc32e05dcf10Chris Banes * @param rectangle The rectangle which the child wishes to be on the screen 238900a00a7d3ba8279294f63994473afc32e05dcf10Chris Banes * in the child's coordinates 239000a00a7d3ba8279294f63994473afc32e05dcf10Chris Banes * @param immediate true to forbid animated or delayed scrolling, false otherwise 239100a00a7d3ba8279294f63994473afc32e05dcf10Chris Banes * @return true if the Behavior handled the request 239200a00a7d3ba8279294f63994473afc32e05dcf10Chris Banes * @see ViewParent#requestChildRectangleOnScreen(View, Rect, boolean) 239300a00a7d3ba8279294f63994473afc32e05dcf10Chris Banes */ 23944cf1d92509224fab3ca69b419a005c536ab75c5cChris Banes public boolean onRequestChildRectangleOnScreen(CoordinatorLayout coordinatorLayout, 239500a00a7d3ba8279294f63994473afc32e05dcf10Chris Banes V child, Rect rectangle, boolean immediate) { 239600a00a7d3ba8279294f63994473afc32e05dcf10Chris Banes return false; 239700a00a7d3ba8279294f63994473afc32e05dcf10Chris Banes } 239800a00a7d3ba8279294f63994473afc32e05dcf10Chris Banes 239900a00a7d3ba8279294f63994473afc32e05dcf10Chris Banes /** 2400e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * Hook allowing a behavior to re-apply a representation of its internal state that had 2401e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * previously been generated by {@link #onSaveInstanceState}. This function will never 2402e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * be called with a null state. 2403e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * 2404e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * @param parent the parent CoordinatorLayout 2405e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * @param child child view to restore from 2406e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * @param state The frozen state that had previously been returned by 2407e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * {@link #onSaveInstanceState}. 2408e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * 2409e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * @see #onSaveInstanceState() 2410e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes */ 2411e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes public void onRestoreInstanceState(CoordinatorLayout parent, V child, Parcelable state) { 2412e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes // no-op 2413e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2414e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2415e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes /** 2416e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * Hook allowing a behavior to generate a representation of its internal state 2417e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * that can later be used to create a new instance with that same state. 2418e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * This state should only contain information that is not persistent or can 2419e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * not be reconstructed later. 2420e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * 2421e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * <p>Behavior state is only saved when both the parent {@link CoordinatorLayout} and 2422e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * a view using this behavior have valid IDs set.</p> 2423e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * 2424e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * @param parent the parent CoordinatorLayout 2425e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * @param child child view to restore from 2426e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * 2427e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * @return Returns a Parcelable object containing the behavior's current dynamic 2428e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * state. 2429e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * 2430e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * @see #onRestoreInstanceState(android.os.Parcelable) 2431e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes * @see View#onSaveInstanceState() 2432e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes */ 2433e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes public Parcelable onSaveInstanceState(CoordinatorLayout parent, V child) { 2434e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes return BaseSavedState.EMPTY_STATE; 2435e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 243626c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes 243726c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes /** 243826c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes * Called when a view is set to dodge view insets. 243926c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes * 244026c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes * <p>This method allows a behavior to update the rectangle that should be dodged. 24416f5e71c633625183188ddd567bab27e8b81c6bffChris Banes * The rectangle should be in the parent's coordinate system and within the child's 24426f5e71c633625183188ddd567bab27e8b81c6bffChris Banes * bounds. If not, a {@link IllegalArgumentException} is thrown.</p> 244326c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes * 244426c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes * @param parent the CoordinatorLayout parent of the view this Behavior is 244526c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes * associated with 244626c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes * @param child the child view of the CoordinatorLayout this Behavior is associated with 244726c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes * @param rect the rect to update with the dodge rectangle 244826c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes * @return true the rect was updated, false if we should use the child's bounds 244926c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes */ 245026c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes public boolean getInsetDodgeRect(@NonNull CoordinatorLayout parent, @NonNull V child, 245126c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes @NonNull Rect rect) { 245226c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes return false; 245326c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes } 2454a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2455a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2456a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2457a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Parameters describing the desired layout for a child of a {@link CoordinatorLayout}. 2458a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2459a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public static class LayoutParams extends ViewGroup.MarginLayoutParams { 2460a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2461a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * A {@link Behavior} that the child view should obey. 2462a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2463a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Behavior mBehavior; 2464a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2465a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean mBehaviorResolved = false; 2466a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2467a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2468a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * A {@link Gravity} value describing how this child view should lay out. 2469a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * If an {@link #setAnchorId(int) anchor} is also specified, the gravity describes 2470a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * how this child view should be positioned relative to its anchored position. 2471a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2472a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public int gravity = Gravity.NO_GRAVITY; 2473a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2474a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2475a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * A {@link Gravity} value describing which edge of a child view's 2476a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link #getAnchorId() anchor} view the child should position itself relative to. 2477a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2478a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public int anchorGravity = Gravity.NO_GRAVITY; 2479a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2480a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2481a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * The index of the horizontal keyline specified to the parent CoordinatorLayout that this 2482a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * child should align relative to. If an {@link #setAnchorId(int) anchor} is present the 2483a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * keyline will be ignored. 2484a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2485a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public int keyline = -1; 2486a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2487a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2488a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * A {@link View#getId() view id} of a descendant view of the CoordinatorLayout that 2489a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * this child should position relative to. 2490a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2491a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell int mAnchorId = View.NO_ID; 2492a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 24931ca24096efc933932416645c546dbd9ac91efbebYuichi Araki /** 24941ca24096efc933932416645c546dbd9ac91efbebYuichi Araki * A {@link Gravity} value describing how this child view insets the CoordinatorLayout. 24951ca24096efc933932416645c546dbd9ac91efbebYuichi Araki * Other child views which are set to dodge the same inset edges will be moved appropriately 24961ca24096efc933932416645c546dbd9ac91efbebYuichi Araki * so that the views do not overlap. 24971ca24096efc933932416645c546dbd9ac91efbebYuichi Araki */ 2498943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki public int insetEdge = Gravity.NO_GRAVITY; 24991ca24096efc933932416645c546dbd9ac91efbebYuichi Araki 25001ca24096efc933932416645c546dbd9ac91efbebYuichi Araki /** 25011ca24096efc933932416645c546dbd9ac91efbebYuichi Araki * A {@link Gravity} value describing how this child view dodges any inset child views in 25021ca24096efc933932416645c546dbd9ac91efbebYuichi Araki * the CoordinatorLayout. Any views which are inset on the same edge as this view is set to 25031ca24096efc933932416645c546dbd9ac91efbebYuichi Araki * dodge will result in this view being moved so that the views do not overlap. 25041ca24096efc933932416645c546dbd9ac91efbebYuichi Araki */ 2505943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki public int dodgeInsetEdges = Gravity.NO_GRAVITY; 2506943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki 2507657ea1100fee4750f148f9d0dcb7e7e2028f105eAurimas Liutikas int mInsetOffsetX; 2508657ea1100fee4750f148f9d0dcb7e7e2028f105eAurimas Liutikas int mInsetOffsetY; 2509943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki 2510a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell View mAnchorView; 2511a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell View mAnchorDirectChild; 2512a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 25135cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell private boolean mDidBlockInteraction; 25145cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell private boolean mDidAcceptNestedScroll; 2515a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes private boolean mDidChangeAfterNestedScroll; 2516a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2517a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final Rect mLastChildRect = new Rect(); 2518a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2519a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Object mBehaviorTag; 2520a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2521a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public LayoutParams(int width, int height) { 2522a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell super(width, height); 2523a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2524a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2525a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell LayoutParams(Context context, AttributeSet attrs) { 2526a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell super(context, attrs); 2527a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2528a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell final TypedArray a = context.obtainStyledAttributes(attrs, 2529c6cbbb50a06ec08e6888bd1c3dfd7fdf588d9db5Chris Banes R.styleable.CoordinatorLayout_Layout); 2530a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2531a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell this.gravity = a.getInteger( 2532c6cbbb50a06ec08e6888bd1c3dfd7fdf588d9db5Chris Banes R.styleable.CoordinatorLayout_Layout_android_layout_gravity, 2533a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Gravity.NO_GRAVITY); 2534c6cbbb50a06ec08e6888bd1c3dfd7fdf588d9db5Chris Banes mAnchorId = a.getResourceId(R.styleable.CoordinatorLayout_Layout_layout_anchor, 2535a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell View.NO_ID); 2536a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell this.anchorGravity = a.getInteger( 2537c6cbbb50a06ec08e6888bd1c3dfd7fdf588d9db5Chris Banes R.styleable.CoordinatorLayout_Layout_layout_anchorGravity, 2538a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Gravity.NO_GRAVITY); 2539a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2540c6cbbb50a06ec08e6888bd1c3dfd7fdf588d9db5Chris Banes this.keyline = a.getInteger(R.styleable.CoordinatorLayout_Layout_layout_keyline, 2541a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell -1); 2542a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2543943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki insetEdge = a.getInt(R.styleable.CoordinatorLayout_Layout_layout_insetEdge, 0); 2544943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki dodgeInsetEdges = a.getInt( 2545943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki R.styleable.CoordinatorLayout_Layout_layout_dodgeInsetEdges, 0); 2546a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mBehaviorResolved = a.hasValue( 2547c6cbbb50a06ec08e6888bd1c3dfd7fdf588d9db5Chris Banes R.styleable.CoordinatorLayout_Layout_layout_behavior); 2548a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mBehaviorResolved) { 2549a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mBehavior = parseBehavior(context, attrs, a.getString( 2550c6cbbb50a06ec08e6888bd1c3dfd7fdf588d9db5Chris Banes R.styleable.CoordinatorLayout_Layout_layout_behavior)); 2551a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2552a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell a.recycle(); 255326c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes 255426c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes if (mBehavior != null) { 255526c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes // If we have a Behavior, dispatch that it has been attached 255626c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes mBehavior.onAttachedToLayoutParams(this); 255726c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes } 2558a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2559a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2560a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public LayoutParams(LayoutParams p) { 2561a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell super(p); 2562a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2563a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2564a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public LayoutParams(MarginLayoutParams p) { 2565a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell super(p); 2566a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2567a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2568a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public LayoutParams(ViewGroup.LayoutParams p) { 2569a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell super(p); 2570a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2571a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2572a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2573a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Get the id of this view's anchor. 2574a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2575a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return A {@link View#getId() view id} or {@link View#NO_ID} if there is no anchor 2576a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 257726c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes @IdRes 2578a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public int getAnchorId() { 2579a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return mAnchorId; 2580a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2581a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2582a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2583c344398708c615b0caba76d287e9ec503afa6819Mady Mellor * Set the id of this view's anchor. 2584a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2585a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>The view with this id must be a descendant of the CoordinatorLayout containing 2586a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * the child view this LayoutParams belongs to. It may not be the child view with 2587a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * this LayoutParams or a descendant of it.</p> 2588a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2589a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param id The {@link View#getId() view id} of the anchor or 2590a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link View#NO_ID} if there is no anchor 2591a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 259226c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes public void setAnchorId(@IdRes int id) { 2593a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell invalidateAnchor(); 2594a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mAnchorId = id; 2595a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2596a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2597a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2598a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Get the behavior governing the layout and interaction of the child view within 2599a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * a parent CoordinatorLayout. 2600a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2601a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return The current behavior or null if no behavior is specified 2602a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 260383418919d2c897e0639999db68831e6c470e6ff4Yuichi Araki @Nullable 2604a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell public Behavior getBehavior() { 2605a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return mBehavior; 2606a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2607a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2608a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2609a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Set the behavior governing the layout and interaction of the child view within 2610a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * a parent CoordinatorLayout. 2611a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2612a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>Setting a new behavior will remove any currently associated 2613a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link Behavior#setTag(android.view.View, Object) Behavior tag}.</p> 2614a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2615a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param behavior The behavior to set or null for no special behavior 2616a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 261726c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes public void setBehavior(@Nullable Behavior behavior) { 2618a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mBehavior != behavior) { 261926c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes if (mBehavior != null) { 262026c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes // First detach any old behavior 262126c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes mBehavior.onDetachedFromLayoutParams(); 262226c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes } 262326c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes 2624a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mBehavior = behavior; 2625a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mBehaviorTag = null; 2626a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mBehaviorResolved = true; 262726c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes 262826c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes if (behavior != null) { 262926c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes // Now dispatch that the Behavior has been attached 263026c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes behavior.onAttachedToLayoutParams(this); 263126c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes } 2632a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2633a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2634a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2635a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2636a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Set the last known position rect for this child view 2637a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param r the rect to set 2638a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2639a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void setLastChildRect(Rect r) { 2640a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mLastChildRect.set(r); 2641a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2642a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2643a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2644a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Get the last known position rect for this child view. 2645a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Note: do not mutate the result of this call. 2646a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2647a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell Rect getLastChildRect() { 2648a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return mLastChildRect; 2649a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2650a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2651a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2652a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Returns true if the anchor id changed to another valid view id since the anchor view 2653a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * was resolved. 2654a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2655a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean checkAnchorChanged() { 2656a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return mAnchorView == null && mAnchorId != View.NO_ID; 2657a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2658a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2659a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2660a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Returns true if the associated Behavior previously blocked interaction with other views 2661a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * below the associated child since the touch behavior tracking was last 2662a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link #resetTouchBehaviorTracking() reset}. 2663a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2664a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @see #isBlockingInteractionBelow(CoordinatorLayout, android.view.View) 2665a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2666a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean didBlockInteraction() { 2667a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mBehavior == null) { 2668a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mDidBlockInteraction = false; 2669a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2670a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return mDidBlockInteraction; 2671a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2672a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2673a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2674a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Check if the associated Behavior wants to block interaction below the given child 2675a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * view. The given child view should be the child this LayoutParams is associated with. 2676a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2677a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>Once interaction is blocked, it will remain blocked until touch interaction tracking 2678a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * is {@link #resetTouchBehaviorTracking() reset}.</p> 2679a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2680a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent CoordinatorLayout 2681a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child view this LayoutParams is associated with 2682a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true to block interaction below the given child 2683a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2684a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean isBlockingInteractionBelow(CoordinatorLayout parent, View child) { 2685a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mDidBlockInteraction) { 2686a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return true; 2687a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2688a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2689a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return mDidBlockInteraction |= mBehavior != null 2690a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell ? mBehavior.blocksInteractionBelow(parent, child) 2691a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell : false; 2692a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2693a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2694a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2695a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Reset tracking of Behavior-specific touch interactions. This includes 2696a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * interaction blocking. 2697a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2698a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @see #isBlockingInteractionBelow(CoordinatorLayout, android.view.View) 2699a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @see #didBlockInteraction() 2700a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2701a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void resetTouchBehaviorTracking() { 2702a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mDidBlockInteraction = false; 2703a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2704a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 27055cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell void resetNestedScroll() { 27065cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell mDidAcceptNestedScroll = false; 27075cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 27085cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 27095cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell void acceptNestedScroll(boolean accept) { 27105cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell mDidAcceptNestedScroll = accept; 27115cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 27125cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 27135cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell boolean isNestedScrollAccepted() { 27145cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell return mDidAcceptNestedScroll; 27155cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell } 27165cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell 2717a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes boolean getChangedAfterNestedScroll() { 2718a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes return mDidChangeAfterNestedScroll; 2719a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 2720a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 2721a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes void setChangedAfterNestedScroll(boolean changed) { 2722a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes mDidChangeAfterNestedScroll = changed; 2723a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 2724a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 2725a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes void resetChangedAfterNestedScroll() { 2726a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes mDidChangeAfterNestedScroll = false; 2727a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes } 2728a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes 2729a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2730a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Check if an associated child view depends on another child view of the CoordinatorLayout. 2731a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2732a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent CoordinatorLayout 2733a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param child the child to check 2734a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param dependency the proposed dependency to check 2735a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return true if child depends on dependency 2736a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2737a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell boolean dependsOn(CoordinatorLayout parent, View child, View dependency) { 2738a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return dependency == mAnchorDirectChild 2739943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki || shouldDodge(dependency, ViewCompat.getLayoutDirection(parent)) 2740a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell || (mBehavior != null && mBehavior.layoutDependsOn(parent, child, dependency)); 2741a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2742a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2743a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2744a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Invalidate the cached anchor view and direct child ancestor of that anchor. 2745a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * The anchor will need to be 2746a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link #findAnchorView(CoordinatorLayout, android.view.View) found} before 2747a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * being used again. 2748a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2749a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell void invalidateAnchor() { 2750a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mAnchorView = mAnchorDirectChild = null; 2751a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2752a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2753a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2754a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Locate the appropriate anchor view by the current {@link #setAnchorId(int) anchor id} 2755a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * or return the cached anchor view if already known. 2756a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * 2757a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param parent the parent CoordinatorLayout 2758a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @param forChild the child this LayoutParams is associated with 2759a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * @return the located descendant anchor view, or null if the anchor id is 2760a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link View#NO_ID}. 2761a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2762a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell View findAnchorView(CoordinatorLayout parent, View forChild) { 2763a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mAnchorId == View.NO_ID) { 2764a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mAnchorView = mAnchorDirectChild = null; 2765a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return null; 2766a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2767a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2768a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mAnchorView == null || !verifyAnchorView(forChild, parent)) { 2769a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell resolveAnchorView(forChild, parent); 2770a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2771a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return mAnchorView; 2772a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2773a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2774a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2775a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Determine the anchor view for the child view this LayoutParams is assigned to. 2776a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Assumes mAnchorId is valid. 2777a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2778375995f4dc8aecb335bb262190d2cd39fdb136d6Chris Banes private void resolveAnchorView(final View forChild, final CoordinatorLayout parent) { 2779a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mAnchorView = parent.findViewById(mAnchorId); 2780a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mAnchorView != null) { 2781375995f4dc8aecb335bb262190d2cd39fdb136d6Chris Banes if (mAnchorView == parent) { 2782375995f4dc8aecb335bb262190d2cd39fdb136d6Chris Banes if (parent.isInEditMode()) { 2783375995f4dc8aecb335bb262190d2cd39fdb136d6Chris Banes mAnchorView = mAnchorDirectChild = null; 2784375995f4dc8aecb335bb262190d2cd39fdb136d6Chris Banes return; 2785375995f4dc8aecb335bb262190d2cd39fdb136d6Chris Banes } 2786375995f4dc8aecb335bb262190d2cd39fdb136d6Chris Banes throw new IllegalStateException( 2787375995f4dc8aecb335bb262190d2cd39fdb136d6Chris Banes "View can not be anchored to the the parent CoordinatorLayout"); 2788375995f4dc8aecb335bb262190d2cd39fdb136d6Chris Banes } 2789375995f4dc8aecb335bb262190d2cd39fdb136d6Chris Banes 2790a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell View directChild = mAnchorView; 2791a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (ViewParent p = mAnchorView.getParent(); 2792a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell p != parent && p != null; 2793a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell p = p.getParent()) { 2794a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (p == forChild) { 2795a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (parent.isInEditMode()) { 2796a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mAnchorView = mAnchorDirectChild = null; 2797a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return; 2798a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2799a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell throw new IllegalStateException( 2800a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell "Anchor must not be a descendant of the anchored view"); 2801a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2802a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (p instanceof View) { 2803a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell directChild = (View) p; 2804a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2805a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2806a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mAnchorDirectChild = directChild; 2807a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } else { 2808a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (parent.isInEditMode()) { 2809a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mAnchorView = mAnchorDirectChild = null; 2810a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return; 2811a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2812a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell throw new IllegalStateException("Could not find CoordinatorLayout descendant view" 2813a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell + " with id " + parent.getResources().getResourceName(mAnchorId) 2814a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell + " to anchor view " + forChild); 2815a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2816a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2817a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2818a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell /** 2819a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * Verify that the previously resolved anchor view is still valid - that it is still 2820a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * a descendant of the expected parent view, it is not the child this LayoutParams 2821a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * is assigned to or a descendant of it, and it has the expected id. 2822a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */ 2823a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell private boolean verifyAnchorView(View forChild, CoordinatorLayout parent) { 2824a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (mAnchorView.getId() != mAnchorId) { 2825a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return false; 2826a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2827a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell 2828a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell View directChild = mAnchorView; 2829a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell for (ViewParent p = mAnchorView.getParent(); 2830a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell p != parent; 2831a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell p = p.getParent()) { 2832a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (p == null || p == forChild) { 2833a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mAnchorView = mAnchorDirectChild = null; 2834a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return false; 2835a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2836a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell if (p instanceof View) { 2837a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell directChild = (View) p; 2838a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2839a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2840a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell mAnchorDirectChild = directChild; 2841a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell return true; 2842a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 2843943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki 2844943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki /** 2845943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki * Checks whether the view with this LayoutParams should dodge the specified view. 2846943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki */ 284726c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes private boolean shouldDodge(View other, int layoutDirection) { 28486206ad57276146c8f70e939fd40ce9c7b88767f6Yuichi Araki LayoutParams lp = (LayoutParams) other.getLayoutParams(); 28496206ad57276146c8f70e939fd40ce9c7b88767f6Yuichi Araki final int absInset = GravityCompat.getAbsoluteGravity(lp.insetEdge, layoutDirection); 28506206ad57276146c8f70e939fd40ce9c7b88767f6Yuichi Araki return absInset != Gravity.NO_GRAVITY && (absInset & 28516206ad57276146c8f70e939fd40ce9c7b88767f6Yuichi Araki GravityCompat.getAbsoluteGravity(dodgeInsetEdges, layoutDirection)) == absInset; 2852943b6775f5dbe28a8ae509e685cf765937b2a76bYuichi Araki } 2853a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell } 285475284fffafacd32f4d178020050589f9e70e5ed9Chris Banes 285517ed3263761329f6aa6796941358c41001fff325Chris Banes private class HierarchyChangeListener implements OnHierarchyChangeListener { 2856657ea1100fee4750f148f9d0dcb7e7e2028f105eAurimas Liutikas HierarchyChangeListener() { 2857657ea1100fee4750f148f9d0dcb7e7e2028f105eAurimas Liutikas } 2858657ea1100fee4750f148f9d0dcb7e7e2028f105eAurimas Liutikas 28590b00489086b22c9688c8c04990dadf54489d45e3Chris Banes @Override 28600b00489086b22c9688c8c04990dadf54489d45e3Chris Banes public void onChildViewAdded(View parent, View child) { 28610b00489086b22c9688c8c04990dadf54489d45e3Chris Banes if (mOnHierarchyChangeListener != null) { 28620b00489086b22c9688c8c04990dadf54489d45e3Chris Banes mOnHierarchyChangeListener.onChildViewAdded(parent, child); 28630b00489086b22c9688c8c04990dadf54489d45e3Chris Banes } 28640b00489086b22c9688c8c04990dadf54489d45e3Chris Banes } 28650b00489086b22c9688c8c04990dadf54489d45e3Chris Banes 28660b00489086b22c9688c8c04990dadf54489d45e3Chris Banes @Override 28670b00489086b22c9688c8c04990dadf54489d45e3Chris Banes public void onChildViewRemoved(View parent, View child) { 286826c07a84cf70ddf44516f7009fe4ce3b5ed65513Chris Banes onChildViewsChanged(EVENT_VIEW_REMOVED); 28690b00489086b22c9688c8c04990dadf54489d45e3Chris Banes 28700b00489086b22c9688c8c04990dadf54489d45e3Chris Banes if (mOnHierarchyChangeListener != null) { 28710b00489086b22c9688c8c04990dadf54489d45e3Chris Banes mOnHierarchyChangeListener.onChildViewRemoved(parent, child); 28720b00489086b22c9688c8c04990dadf54489d45e3Chris Banes } 28730b00489086b22c9688c8c04990dadf54489d45e3Chris Banes } 28740b00489086b22c9688c8c04990dadf54489d45e3Chris Banes } 28750b00489086b22c9688c8c04990dadf54489d45e3Chris Banes 2876e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes @Override 2877e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes protected void onRestoreInstanceState(Parcelable state) { 2878b8af67a0b7896d08b81a803b3880dafaddc7e0bcAlan Viverette if (!(state instanceof SavedState)) { 2879b8af67a0b7896d08b81a803b3880dafaddc7e0bcAlan Viverette super.onRestoreInstanceState(state); 2880b8af67a0b7896d08b81a803b3880dafaddc7e0bcAlan Viverette return; 2881b8af67a0b7896d08b81a803b3880dafaddc7e0bcAlan Viverette } 2882b8af67a0b7896d08b81a803b3880dafaddc7e0bcAlan Viverette 2883e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final SavedState ss = (SavedState) state; 2884e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes super.onRestoreInstanceState(ss.getSuperState()); 2885e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2886e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final SparseArray<Parcelable> behaviorStates = ss.behaviorStates; 2887e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2888e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes for (int i = 0, count = getChildCount(); i < count; i++) { 2889e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final View child = getChildAt(i); 2890e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final int childId = child.getId(); 2891e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final LayoutParams lp = getResolvedLayoutParams(child); 2892e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final Behavior b = lp.getBehavior(); 2893e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2894e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes if (childId != NO_ID && b != null) { 2895e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes Parcelable savedState = behaviorStates.get(childId); 2896e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes if (savedState != null) { 2897e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes b.onRestoreInstanceState(this, child, savedState); 2898e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2899e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2900e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2901e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2902e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2903e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes @Override 2904e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes protected Parcelable onSaveInstanceState() { 2905e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final SavedState ss = new SavedState(super.onSaveInstanceState()); 2906e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2907e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final SparseArray<Parcelable> behaviorStates = new SparseArray<>(); 2908e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes for (int i = 0, count = getChildCount(); i < count; i++) { 2909e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final View child = getChildAt(i); 2910e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final int childId = child.getId(); 2911e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 2912e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final Behavior b = lp.getBehavior(); 2913e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2914e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes if (childId != NO_ID && b != null) { 2915e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes // If the child has an ID and a Behavior, let it save some state... 2916e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes Parcelable state = b.onSaveInstanceState(this, child); 2917e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes if (state != null) { 2918e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes behaviorStates.append(childId, state); 2919e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2920e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2921e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2922e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes ss.behaviorStates = behaviorStates; 2923e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes return ss; 2924e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2925e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 292600a00a7d3ba8279294f63994473afc32e05dcf10Chris Banes @Override 292700a00a7d3ba8279294f63994473afc32e05dcf10Chris Banes public boolean requestChildRectangleOnScreen(View child, Rect rectangle, boolean immediate) { 292800a00a7d3ba8279294f63994473afc32e05dcf10Chris Banes final CoordinatorLayout.LayoutParams lp = (LayoutParams) child.getLayoutParams(); 292900a00a7d3ba8279294f63994473afc32e05dcf10Chris Banes final Behavior behavior = lp.getBehavior(); 293000a00a7d3ba8279294f63994473afc32e05dcf10Chris Banes 293100a00a7d3ba8279294f63994473afc32e05dcf10Chris Banes if (behavior != null 29324cf1d92509224fab3ca69b419a005c536ab75c5cChris Banes && behavior.onRequestChildRectangleOnScreen(this, child, rectangle, immediate)) { 293300a00a7d3ba8279294f63994473afc32e05dcf10Chris Banes return true; 293400a00a7d3ba8279294f63994473afc32e05dcf10Chris Banes } 293500a00a7d3ba8279294f63994473afc32e05dcf10Chris Banes 293600a00a7d3ba8279294f63994473afc32e05dcf10Chris Banes return super.requestChildRectangleOnScreen(child, rectangle, immediate); 293700a00a7d3ba8279294f63994473afc32e05dcf10Chris Banes } 293800a00a7d3ba8279294f63994473afc32e05dcf10Chris Banes 29393035e10317eb12c58153d8c651a791896ea3094eChris Banes private void setupForInsets() { 29403035e10317eb12c58153d8c651a791896ea3094eChris Banes if (Build.VERSION.SDK_INT < 21) { 29413035e10317eb12c58153d8c651a791896ea3094eChris Banes return; 29423035e10317eb12c58153d8c651a791896ea3094eChris Banes } 29433035e10317eb12c58153d8c651a791896ea3094eChris Banes 29443035e10317eb12c58153d8c651a791896ea3094eChris Banes if (ViewCompat.getFitsSystemWindows(this)) { 29453035e10317eb12c58153d8c651a791896ea3094eChris Banes if (mApplyWindowInsetsListener == null) { 29463035e10317eb12c58153d8c651a791896ea3094eChris Banes mApplyWindowInsetsListener = 29473035e10317eb12c58153d8c651a791896ea3094eChris Banes new android.support.v4.view.OnApplyWindowInsetsListener() { 29483035e10317eb12c58153d8c651a791896ea3094eChris Banes @Override 29493035e10317eb12c58153d8c651a791896ea3094eChris Banes public WindowInsetsCompat onApplyWindowInsets(View v, 29503035e10317eb12c58153d8c651a791896ea3094eChris Banes WindowInsetsCompat insets) { 29513035e10317eb12c58153d8c651a791896ea3094eChris Banes return setWindowInsets(insets); 29523035e10317eb12c58153d8c651a791896ea3094eChris Banes } 29533035e10317eb12c58153d8c651a791896ea3094eChris Banes }; 29543035e10317eb12c58153d8c651a791896ea3094eChris Banes } 29553035e10317eb12c58153d8c651a791896ea3094eChris Banes // First apply the insets listener 29563035e10317eb12c58153d8c651a791896ea3094eChris Banes ViewCompat.setOnApplyWindowInsetsListener(this, mApplyWindowInsetsListener); 29573035e10317eb12c58153d8c651a791896ea3094eChris Banes 29583035e10317eb12c58153d8c651a791896ea3094eChris Banes // Now set the sys ui flags to enable us to lay out in the window insets 29593035e10317eb12c58153d8c651a791896ea3094eChris Banes setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE 29603035e10317eb12c58153d8c651a791896ea3094eChris Banes | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); 29613035e10317eb12c58153d8c651a791896ea3094eChris Banes } else { 29623035e10317eb12c58153d8c651a791896ea3094eChris Banes ViewCompat.setOnApplyWindowInsetsListener(this, null); 29633035e10317eb12c58153d8c651a791896ea3094eChris Banes } 29643035e10317eb12c58153d8c651a791896ea3094eChris Banes } 29653035e10317eb12c58153d8c651a791896ea3094eChris Banes 296605f5ba020fa6caa658c75b6d77436aa980ca0fccChris Banes protected static class SavedState extends AbsSavedState { 2967e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes SparseArray<Parcelable> behaviorStates; 2968e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 296962ab25d71ccfa775a8bd2add7b41277bc4e14bbcChris Banes public SavedState(Parcel source, ClassLoader loader) { 297005f5ba020fa6caa658c75b6d77436aa980ca0fccChris Banes super(source, loader); 2971e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2972e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final int size = source.readInt(); 2973e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2974e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final int[] ids = new int[size]; 2975e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes source.readIntArray(ids); 2976e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 297762ab25d71ccfa775a8bd2add7b41277bc4e14bbcChris Banes final Parcelable[] states = source.readParcelableArray(loader); 2978e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2979e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes behaviorStates = new SparseArray<>(size); 2980e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes for (int i = 0; i < size; i++) { 2981e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes behaviorStates.append(ids[i], states[i]); 2982e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2983e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2984e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2985e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes public SavedState(Parcelable superState) { 2986e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes super(superState); 2987e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 2988e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2989e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes @Override 2990e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes public void writeToParcel(Parcel dest, int flags) { 2991e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes super.writeToParcel(dest, flags); 2992e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2993e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final int size = behaviorStates != null ? behaviorStates.size() : 0; 2994e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes dest.writeInt(size); 2995e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2996e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final int[] ids = new int[size]; 2997e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes final Parcelable[] states = new Parcelable[size]; 2998e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 2999e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes for (int i = 0; i < size; i++) { 3000e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes ids[i] = behaviorStates.keyAt(i); 3001e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes states[i] = behaviorStates.valueAt(i); 3002e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 3003e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes dest.writeIntArray(ids); 3004e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes dest.writeParcelableArray(states, flags); 3005e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 3006e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 3007e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 300862ab25d71ccfa775a8bd2add7b41277bc4e14bbcChris Banes public static final Parcelable.Creator<SavedState> CREATOR 300962ab25d71ccfa775a8bd2add7b41277bc4e14bbcChris Banes = ParcelableCompat.newCreator(new ParcelableCompatCreatorCallbacks<SavedState>() { 301062ab25d71ccfa775a8bd2add7b41277bc4e14bbcChris Banes @Override 301162ab25d71ccfa775a8bd2add7b41277bc4e14bbcChris Banes public SavedState createFromParcel(Parcel in, ClassLoader loader) { 301262ab25d71ccfa775a8bd2add7b41277bc4e14bbcChris Banes return new SavedState(in, loader); 301362ab25d71ccfa775a8bd2add7b41277bc4e14bbcChris Banes } 3014e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes 301562ab25d71ccfa775a8bd2add7b41277bc4e14bbcChris Banes @Override 301662ab25d71ccfa775a8bd2add7b41277bc4e14bbcChris Banes public SavedState[] newArray(int size) { 301762ab25d71ccfa775a8bd2add7b41277bc4e14bbcChris Banes return new SavedState[size]; 301862ab25d71ccfa775a8bd2add7b41277bc4e14bbcChris Banes } 301962ab25d71ccfa775a8bd2add7b41277bc4e14bbcChris Banes }); 3020e52e16988e2500e20052ddd70920f950f4eb4f79Chris Banes } 3021a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell} 3022