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