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