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