CoordinatorLayout.java revision 878384f1e6de7bd9196958224ced1ecfca3be6a7
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;
26a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.os.Build;
27a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.os.SystemClock;
28a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.support.design.R;
29a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.support.v4.view.GravityCompat;
30a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.support.v4.view.NestedScrollingParent;
31a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.support.v4.view.NestedScrollingParentHelper;
32a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.support.v4.view.ViewCompat;
33a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.text.TextUtils;
34a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.util.AttributeSet;
35a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.util.Log;
36a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.view.Gravity;
37a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.view.MotionEvent;
38a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.view.View;
39a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.view.ViewGroup;
40a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.view.ViewParent;
41a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport android.view.ViewTreeObserver;
42a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
43a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport java.lang.annotation.Retention;
44a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport java.lang.annotation.RetentionPolicy;
45a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport java.lang.reflect.Constructor;
46a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport java.util.ArrayList;
47a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport java.util.Collections;
48a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport java.util.Comparator;
49a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport java.util.HashMap;
50a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport java.util.List;
51a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellimport java.util.Map;
52a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
53a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell/**
54a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * CoordinatorLayout is a super-powered {@link android.widget.FrameLayout FrameLayout}.
55a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell *
56a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>CoordinatorLayout is intended for two primary use cases:</p>
57a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <ol>
58a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell *     <li>As a top-level application decor or chrome layout</li>
59a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell *     <li>As a container for a specific interaction with one or more child views</li>
60a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * </ol>
61a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell *
62a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>By specifying {@link CoordinatorLayout.Behavior Behaviors} for child views of a
63a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * CoordinatorLayout you can provide many different interactions within a single parent and those
64a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * views can also interact with one another. View classes can specify a default behavior when
65a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * used as a child of a CoordinatorLayout using the
66a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link CoordinatorLayout.DefaultBehavior DefaultBehavior} annotation.</p>
67a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell *
68a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>Behaviors may be used to implement a variety of interactions and additional layout
69a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * modifications ranging from sliding drawers and panels to swipe-dismissable elements and buttons
70a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * that stick to other elements as they move and animate.</p>
71a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell *
72a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * <p>Children of a CoordinatorLayout may have an
73a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * {@link CoordinatorLayout.LayoutParams#setAnchorId(int) anchor}. This view id must correspond
74a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * to an arbitrary descendant of the CoordinatorLayout, but it may not be the anchored child itself
75a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * or a descendant of the anchored child. This can be used to place floating views relative to
76a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell * other arbitrary content panes.</p>
77a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell */
78a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powellpublic class CoordinatorLayout extends ViewGroup implements NestedScrollingParent {
79a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    static final String TAG = "CoordinatorLayout";
80a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    static final String WIDGET_PACKAGE_NAME = CoordinatorLayout.class.getPackage().getName();
81a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
82a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    static {
83a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        if (Build.VERSION.SDK_INT >= 21) {
84a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            TOP_SORTED_CHILDREN_COMPARATOR = new ViewElevationComparator();
85a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        } else {
86a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            TOP_SORTED_CHILDREN_COMPARATOR = null;
87a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
88a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
89a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
90a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    static final Class<?>[] CONSTRUCTOR_PARAMS = new Class<?>[] {
91a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            Context.class,
92a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            AttributeSet.class
93a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    };
94a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
95a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    static final ThreadLocal<Map<String, Constructor<Behavior>>> sConstructors =
96a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            new ThreadLocal<>();
97a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
98a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    final Comparator<View> mLayoutDependencyComparator = new Comparator<View>() {
99a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        @Override
100a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        public int compare(View lhs, View rhs) {
101a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            if (lhs == rhs) {
102a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                return 0;
103a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            } else if (((LayoutParams) lhs.getLayoutParams()).dependsOn(
104a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                    CoordinatorLayout.this, lhs, rhs)) {
105a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                return 1;
106a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            } else if (((LayoutParams) rhs.getLayoutParams()).dependsOn(
107a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                    CoordinatorLayout.this, rhs, lhs)) {
108a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                return -1;
109a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            } else {
110a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                return 0;
111a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            }
112a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
113a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    };
114a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
115a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    static final Comparator<View> TOP_SORTED_CHILDREN_COMPARATOR;
116a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
117a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    private final List<View> mDependencySortedChildren = new ArrayList<View>();
118a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    private final List<View> mTempList1 = new ArrayList<>();
119a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    private final List<View> mTempDependenciesList = new ArrayList<>();
120a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    private final Rect mTempRect1 = new Rect();
121a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    private final Rect mTempRect2 = new Rect();
122a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    private final Rect mTempRect3 = new Rect();
1235cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell    private final int[] mTempIntPair = new int[2];
124a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    private Paint mScrimPaint;
125a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
126a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    private boolean mIsAttachedToWindow;
127a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
128a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    private int[] mKeylines;
129a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
130a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    private View mBehaviorTouchView;
1315cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell    private View mNestedScrollingDirectChild;
1325cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell    private View mNestedScrollingTarget;
133a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
134a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    private OnPreDrawListener mOnPreDrawListener;
135a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    private boolean mNeedsPreDrawListener;
136a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
137a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    private final NestedScrollingParentHelper mNestedScrollingParentHelper =
138a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            new NestedScrollingParentHelper(this);
139a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
140a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    public CoordinatorLayout(Context context) {
141a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        this(context, null);
142a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
143a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
144a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    public CoordinatorLayout(Context context, AttributeSet attrs) {
145a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        this(context, attrs, 0);
146a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
147a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
148a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    public CoordinatorLayout(Context context, AttributeSet attrs, int defStyleAttr) {
149a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        super(context, attrs, defStyleAttr);
150a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
151a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CoordinatorLayout,
152a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                defStyleAttr, 0);
153a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final int keylineArrayRes = a.getResourceId(R.styleable.CoordinatorLayout_keylines, 0);
154a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        if (keylineArrayRes != 0) {
155a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            final Resources res = context.getResources();
156a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            mKeylines = res.getIntArray(keylineArrayRes);
157a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            final float density = res.getDisplayMetrics().density;
158a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            final int count = mKeylines.length;
159a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            for (int i = 0; i < count; i++) {
160a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                mKeylines[i] *= density;
161a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            }
162a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
163a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        a.recycle();
164a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
165a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
166a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    @Override
167a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    public void onAttachedToWindow() {
168a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        super.onAttachedToWindow();
1695cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        resetTouchBehaviors();
170a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        if (mNeedsPreDrawListener) {
171a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            if (mOnPreDrawListener == null) {
172a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                mOnPreDrawListener = new OnPreDrawListener();
173a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            }
174a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            final ViewTreeObserver vto = getViewTreeObserver();
175a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            vto.addOnPreDrawListener(mOnPreDrawListener);
176a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
177a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        mIsAttachedToWindow = true;
178a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
179a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
180a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    @Override
181a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    public void onDetachedFromWindow() {
182a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        super.onDetachedFromWindow();
1835cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        resetTouchBehaviors();
184a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        if (mNeedsPreDrawListener && mOnPreDrawListener != null) {
185a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            final ViewTreeObserver vto = getViewTreeObserver();
186a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            vto.removeOnPreDrawListener(mOnPreDrawListener);
187a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
1885cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        if (mNestedScrollingTarget != null) {
1895cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            onStopNestedScroll(mNestedScrollingTarget);
1905cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        }
191a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        mIsAttachedToWindow = false;
192a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
193a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
194a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    /**
195a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * Reset all Behavior-related tracking records either to clean up or in preparation
196a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * for a new event stream. This should be called when attached or detached from a window,
197a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * in response to an UP or CANCEL event, when intercept is request-disallowed
198a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * and similar cases where an event stream in progress will be aborted.
199a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     */
2005cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell    private void resetTouchBehaviors() {
201a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        if (mBehaviorTouchView != null) {
202a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            final Behavior b = ((LayoutParams) mBehaviorTouchView.getLayoutParams()).getBehavior();
203a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            if (b != null) {
204a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                final long now = SystemClock.uptimeMillis();
205a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                final MotionEvent cancelEvent = MotionEvent.obtain(now, now,
206a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                        MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0);
207a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                b.onTouchEvent(this, mBehaviorTouchView, cancelEvent);
208a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                cancelEvent.recycle();
209a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            }
210a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            mBehaviorTouchView = null;
211a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
212a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
213a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final int childCount = getChildCount();
214a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        for (int i = 0; i < childCount; i++) {
215a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            final View child = getChildAt(i);
216a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
217a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            lp.resetTouchBehaviorTracking();
218a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
219a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
220a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
221a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    /**
222a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * Populate a list with the current child views, sorted such that the topmost views
223a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * in z-order are at the front of the list. Useful for hit testing and event dispatch.
224a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     */
225a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    private void getTopSortedChildren(List<View> out) {
226a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        out.clear();
227a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
228a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final boolean useCustomOrder = isChildrenDrawingOrderEnabled();
229a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final int childCount = getChildCount();
230a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        for (int i = childCount - 1; i >= 0; i--) {
231a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            final int childIndex = useCustomOrder ? getChildDrawingOrder(childCount, i) : i;
232a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            final View child = getChildAt(childIndex);
233a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            out.add(child);
234a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
235a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
236a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        if (TOP_SORTED_CHILDREN_COMPARATOR != null) {
237a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            Collections.sort(out, TOP_SORTED_CHILDREN_COMPARATOR);
238a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
239a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
240a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
241a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    private boolean performIntercept(MotionEvent ev) {
242a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        boolean intercepted = false;
243a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        boolean newBlock = false;
244a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
245a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        MotionEvent cancelEvent = null;
246a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
247a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final int action = ev.getActionMasked();
248a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
249a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        final List<View> topmostChildList = mTempList1;
250a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        getTopSortedChildren(topmostChildList);
251a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
252a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        // Let topmost child views inspect first
253a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final int childCount = topmostChildList.size();
254a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        for (int i = 0; i < childCount; i++) {
255a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            final View child = topmostChildList.get(i);
256a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
257a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            final Behavior b = lp.getBehavior();
258a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
259a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            if ((intercepted || newBlock) && action != MotionEvent.ACTION_DOWN) {
260a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                // Cancel all behaviors beneath the one that intercepted.
261a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                // If the event is "down" then we don't have anything to cancel yet.
262a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                if (b != null) {
263a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                    if (cancelEvent != null) {
264a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                        final long now = SystemClock.uptimeMillis();
265a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                        cancelEvent = MotionEvent.obtain(now, now,
266a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                                MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0);
267a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                    }
268a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                    b.onInterceptTouchEvent(this, child, cancelEvent);
269a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                }
270a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                continue;
271a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            }
272a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
273a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            if (!intercepted && b != null
274a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                    && (intercepted = b.onInterceptTouchEvent(this, child, ev))) {
275a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                mBehaviorTouchView = child;
276a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            }
277a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
278a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            // Don't keep going if we're not allowing interaction below this.
279a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            // Setting newBlock will make sure we cancel the rest of the behaviors.
280a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            final boolean wasBlocking = lp.didBlockInteraction();
281a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            final boolean isBlocking = lp.isBlockingInteractionBelow(this, child);
282a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            newBlock = isBlocking && !wasBlocking;
283a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            if (isBlocking && !newBlock) {
284a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                // Stop here since we don't have anything more to cancel - we already did
285a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                // when the behavior first started blocking things below this point.
286a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                break;
287a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            }
288a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
289a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
290a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        topmostChildList.clear();
291a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
292a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        return intercepted;
293a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
294a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
295a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    @Override
296a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    public boolean onInterceptTouchEvent(MotionEvent ev) {
297a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        MotionEvent cancelEvent = null;
298a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
299a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final int action = ev.getActionMasked();
300a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
301a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        // Make sure we reset in case we had missed a previous important event.
302a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        if (action == MotionEvent.ACTION_DOWN) {
3035cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            resetTouchBehaviors();
304a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
305a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
306a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final boolean intercepted = performIntercept(ev);
307a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
308a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        if (cancelEvent != null) {
309a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            cancelEvent.recycle();
310a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
311a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
312a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
3135cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            resetTouchBehaviors();
314a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
315a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
316a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        return intercepted;
317a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
318a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
319a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    @Override
320a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    public boolean onTouchEvent(MotionEvent ev) {
321a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        boolean handled = false;
322a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        boolean cancelSuper = false;
323a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        MotionEvent cancelEvent = null;
324a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
325a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final int action = ev.getActionMasked();
326a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
327a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        if (mBehaviorTouchView != null || (cancelSuper = performIntercept(ev))) {
328a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            // Safe since performIntercept guarantees that
329a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            // mBehaviorTouchView != null if it returns true
330ecc58a45a7bdd60d9b71e6c413b80a3f8cf85822Chris Banes            final LayoutParams lp = (LayoutParams) mBehaviorTouchView.getLayoutParams();
331ecc58a45a7bdd60d9b71e6c413b80a3f8cf85822Chris Banes            final Behavior b = lp.getBehavior();
332ecc58a45a7bdd60d9b71e6c413b80a3f8cf85822Chris Banes            if (b != null) {
333ecc58a45a7bdd60d9b71e6c413b80a3f8cf85822Chris Banes                b.onTouchEvent(this, mBehaviorTouchView, ev);
334ecc58a45a7bdd60d9b71e6c413b80a3f8cf85822Chris Banes            }
335a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
336a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
337a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        // Keep the super implementation correct
338a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        if (mBehaviorTouchView == null) {
339a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            handled |= super.onTouchEvent(ev);
340a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        } else if (cancelSuper) {
341a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            if (cancelEvent != null) {
342a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                final long now = SystemClock.uptimeMillis();
343a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                cancelEvent = MotionEvent.obtain(now, now,
344a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                        MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0);
345a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            }
346a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            super.onTouchEvent(cancelEvent);
347a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
348a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
349a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        if (!handled && action == MotionEvent.ACTION_DOWN) {
350a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
351a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
352a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
353a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        if (cancelEvent != null) {
354a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            cancelEvent.recycle();
355a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
356a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
357a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
3585cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            resetTouchBehaviors();
359a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
360a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
361a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        return handled;
362a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
363a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
364a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    @Override
365a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
366a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        super.requestDisallowInterceptTouchEvent(disallowIntercept);
367a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        if (disallowIntercept) {
3685cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            resetTouchBehaviors();
369a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
370a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
371a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
372a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    private int getKeyline(int index) {
373a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        if (mKeylines == null) {
374a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            Log.e(TAG, "No keylines defined for " + this + " - attempted index lookup " + index);
375a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            return 0;
376a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
377a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
378a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        if (index < 0 || index >= mKeylines.length) {
379a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            Log.e(TAG, "Keyline index " + index + " out of range for " + this);
380a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            return 0;
381a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
382a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
383a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        return mKeylines[index];
384a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
385a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
386a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    static Behavior parseBehavior(Context context, AttributeSet attrs, String name) {
387a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        if (TextUtils.isEmpty(name)) {
388a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            return null;
389a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
390a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
391a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final String fullName;
392a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        if (name.startsWith(".")) {
393a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            // Relative to the app package. Prepend the app package name.
394a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            fullName = context.getPackageName() + name;
395a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        } else if (name.indexOf('.') >= 0) {
396a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            // Fully qualified package name.
397a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            fullName = name;
398a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        } else {
399a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            // Assume stock behavior in this package.
400a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            fullName = WIDGET_PACKAGE_NAME + '.' + name;
401a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
402a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
403a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        try {
404a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            Map<String, Constructor<Behavior>> constructors = sConstructors.get();
405a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            if (constructors == null) {
406a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                constructors = new HashMap<>();
407a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                sConstructors.set(constructors);
408a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            }
409a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            Constructor<Behavior> c = constructors.get(fullName);
410a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            if (c == null) {
411a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                final Class<Behavior> clazz = (Class<Behavior>) Class.forName(fullName, true,
412a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                        context.getClassLoader());
413a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                c = clazz.getConstructor(CONSTRUCTOR_PARAMS);
414878384f1e6de7bd9196958224ced1ecfca3be6a7Chris Banes                c.setAccessible(true);
415a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                constructors.put(fullName, c);
416a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            }
417a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            return c.newInstance(context, attrs);
418a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        } catch (Exception e) {
419a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            throw new RuntimeException("Could not inflate Behavior subclass " + fullName, e);
420a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
421a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
422a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
423a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    LayoutParams getResolvedLayoutParams(View child) {
424a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final LayoutParams result = (LayoutParams) child.getLayoutParams();
425a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        if (!result.mBehaviorResolved) {
42642058bc54bdb89b9c9429bf6cbd3260787cf0523Adam Powell            Class<?> childClass = child.getClass();
42742058bc54bdb89b9c9429bf6cbd3260787cf0523Adam Powell            DefaultBehavior defaultBehavior = null;
42842058bc54bdb89b9c9429bf6cbd3260787cf0523Adam Powell            while (childClass != null &&
42942058bc54bdb89b9c9429bf6cbd3260787cf0523Adam Powell                    (defaultBehavior = childClass.getAnnotation(DefaultBehavior.class)) == null) {
43042058bc54bdb89b9c9429bf6cbd3260787cf0523Adam Powell                childClass = childClass.getSuperclass();
43142058bc54bdb89b9c9429bf6cbd3260787cf0523Adam Powell            }
432a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            if (defaultBehavior != null) {
433a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                try {
434a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                    result.setBehavior(defaultBehavior.value().newInstance());
435a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                } catch (Exception e) {
436a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                    Log.e(TAG, "Default behavior class " + defaultBehavior.value().getName() +
437a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                            " could not be instantiated. Did you forget a default constructor?", e);
438a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                }
439a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            }
440a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            result.mBehaviorResolved = true;
441a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
442a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        return result;
443a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
444a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
445a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    private void prepareChildren() {
446a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final int childCount = getChildCount();
447a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
448a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        boolean resortRequired = mDependencySortedChildren.size() != childCount;
449a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
450a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        for (int i = 0; i < childCount; i++) {
451a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            final View child = getChildAt(i);
452a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            final LayoutParams lp = getResolvedLayoutParams(child);
453a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            if (!resortRequired && lp.isDirty(this, child)) {
454a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                resortRequired = true;
455a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            }
456a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            lp.findAnchorView(this, child);
457a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
458a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
459a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        if (resortRequired) {
460a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            mDependencySortedChildren.clear();
461a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            for (int i = 0; i < childCount; i++) {
462a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                mDependencySortedChildren.add(getChildAt(i));
463a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            }
464a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            Collections.sort(mDependencySortedChildren, mLayoutDependencyComparator);
465a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
466a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
467a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
468a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    /**
469a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * Retrieve the transformed bounding rect of an arbitrary descendant view.
470a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * This does not need to be a direct child.
471a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     *
472a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * @param descendant descendant view to reference
473a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * @param out rect to set to the bounds of the descendant view
474a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     */
475a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    void getDescendantRect(View descendant, Rect out) {
476a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        ViewGroupUtils.getDescendantRect(this, descendant, out);
477a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
478a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
479a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    @Override
480a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    protected int getSuggestedMinimumWidth() {
481a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        return Math.max(super.getSuggestedMinimumWidth(), getPaddingLeft() + getPaddingRight());
482a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
483a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
484a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    @Override
485a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    protected int getSuggestedMinimumHeight() {
486a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        return Math.max(super.getSuggestedMinimumHeight(), getPaddingTop() + getPaddingBottom());
487a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
488a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
489a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    /**
490a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * Called to measure each individual child view unless a
491a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * {@link CoordinatorLayout.Behavior Behavior} is present. The Behavior may choose to delegate
492a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * child measurement to this method.
493a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     *
494a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * @param child the child to measure
495a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * @param parentWidthMeasureSpec the width requirements for this view
496a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * @param widthUsed extra space that has been used up by the parent
497a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     *        horizontally (possibly by other children of the parent)
498a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * @param parentHeightMeasureSpec the height requirements for this view
499a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * @param heightUsed extra space that has been used up by the parent
500a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     *        vertically (possibly by other children of the parent)
501a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     */
502a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    public void onMeasureChild(View child, int parentWidthMeasureSpec, int widthUsed,
503a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            int parentHeightMeasureSpec, int heightUsed) {
504a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        measureChildWithMargins(child, parentWidthMeasureSpec, widthUsed,
505a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                parentHeightMeasureSpec, heightUsed);
506a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
507a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
508a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    @Override
509a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
510a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        prepareChildren();
511a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        ensurePreDrawListener();
512a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
513a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final int paddingLeft = getPaddingLeft();
514a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final int paddingTop = getPaddingTop();
515a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final int paddingRight = getPaddingRight();
516a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final int paddingBottom = getPaddingBottom();
517a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final int layoutDirection = ViewCompat.getLayoutDirection(this);
518a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final boolean isRtl = layoutDirection == ViewCompat.LAYOUT_DIRECTION_RTL;
519a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
520a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
521a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
522a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final int widthPadding = paddingLeft + paddingRight;
523a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final int heightPadding = paddingTop + paddingBottom;
524a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        int widthUsed = getSuggestedMinimumWidth();
525a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        int heightUsed = getSuggestedMinimumHeight();
526a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        int childState = 0;
527a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
528a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final int childCount = mDependencySortedChildren.size();
529a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        for (int i = 0; i < childCount; i++) {
530a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            final View child = mDependencySortedChildren.get(i);
531a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
532a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
533a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            int keylineWidthUsed = 0;
534a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            if (lp.keyline >= 0 && widthMode != MeasureSpec.UNSPECIFIED) {
535a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                final int keylinePos = getKeyline(lp.keyline);
536a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                final int keylineGravity = GravityCompat.getAbsoluteGravity(
537a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                        resolveKeylineGravity(lp.gravity), layoutDirection)
538a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                        & Gravity.HORIZONTAL_GRAVITY_MASK;
539a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                if ((keylineGravity == Gravity.LEFT && !isRtl)
540a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                        || (keylineGravity == Gravity.RIGHT && isRtl)) {
541a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                    keylineWidthUsed = Math.max(0, widthSize - paddingRight - keylinePos);
542a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                } else if ((keylineGravity == Gravity.RIGHT && !isRtl)
543a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                        || (keylineGravity == Gravity.LEFT && isRtl)) {
544a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                    keylineWidthUsed = Math.max(0, keylinePos - paddingLeft);
545a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                }
546a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            }
547a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
548a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            final Behavior b = lp.getBehavior();
549a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            if (b == null || !b.onMeasureChild(this, child, widthMeasureSpec, keylineWidthUsed,
550a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                    heightMeasureSpec, 0)) {
551a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                onMeasureChild(child, widthMeasureSpec, keylineWidthUsed,
552a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                        heightMeasureSpec, 0);
553a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            }
554a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
555a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            widthUsed = Math.max(widthUsed, widthPadding + child.getMeasuredWidth() +
556a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                    lp.leftMargin + lp.rightMargin);
557a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
558a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            heightUsed = Math.max(heightUsed, heightPadding + child.getMeasuredHeight() +
559a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                    lp.topMargin + lp.bottomMargin);
560a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            childState = ViewCompat.combineMeasuredStates(childState,
561a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                    ViewCompat.getMeasuredState(child));
562a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
563a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
564a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final int width = ViewCompat.resolveSizeAndState(widthUsed, widthMeasureSpec,
565a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                childState & ViewCompat.MEASURED_STATE_MASK);
566a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final int height = ViewCompat.resolveSizeAndState(heightUsed, heightMeasureSpec,
567a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                childState << ViewCompat.MEASURED_HEIGHT_STATE_SHIFT);
568a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        setMeasuredDimension(width, height);
569a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
570a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
571a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    /**
572a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * Called to lay out each individual child view unless a
573a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * {@link CoordinatorLayout.Behavior Behavior} is present. The Behavior may choose to
574a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * delegate child measurement to this method.
575a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     *
576a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * @param child child view to lay out
577a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * @param layoutDirection the resolved layout direction for the CoordinatorLayout, such as
578a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     *                        {@link ViewCompat#LAYOUT_DIRECTION_LTR} or
579a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     *                        {@link ViewCompat#LAYOUT_DIRECTION_RTL}.
580a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     */
581a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    public void onLayoutChild(View child, int layoutDirection) {
582a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final LayoutParams lp = (LayoutParams) child.getLayoutParams();
583a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        if (lp.checkAnchorChanged()) {
584a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            throw new IllegalStateException("An anchor may not be changed after CoordinatorLayout"
585a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                    + " measurement begins before layout is complete.");
586a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
587a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        if (lp.mAnchorView != null) {
588a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            layoutChildWithAnchor(child, lp.mAnchorView, layoutDirection);
589a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        } else if (lp.keyline >= 0) {
590a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            layoutChildWithKeyline(child, lp.keyline, layoutDirection);
591a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        } else {
592a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            layoutChild(child, layoutDirection);
593a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
594a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
595a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
596a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    @Override
597a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    protected void onLayout(boolean changed, int l, int t, int r, int b) {
598a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final int layoutDirection = ViewCompat.getLayoutDirection(this);
599a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final int childCount = mDependencySortedChildren.size();
600a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        for (int i = 0; i < childCount; i++) {
601a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            final View child = mDependencySortedChildren.get(i);
602a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
603a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            final Behavior behavior = lp.getBehavior();
604a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
605a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            if (behavior == null || !behavior.onLayoutChild(this, child, layoutDirection)) {
606a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                onLayoutChild(child, layoutDirection);
607a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            }
608a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
609a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
610a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
611a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    /**
612a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * Mark the last known child position rect for the given child view.
613a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * This will be used when checking if a child view's position has changed between frames.
614a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * The rect used here should be one returned by
615a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * {@link #getChildRect(android.view.View, boolean, android.graphics.Rect)}, with translation
616a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * disabled.
617a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     *
618a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * @param child child view to set for
619a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * @param r rect to set
620a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     */
621a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    void recordLastChildRect(View child, Rect r) {
622a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final LayoutParams lp = (LayoutParams) child.getLayoutParams();
623a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        lp.setLastChildRect(r);
624a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
625a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
626a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    /**
627a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * Get the last known child rect recorded by
628a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * {@link #recordLastChildRect(android.view.View, android.graphics.Rect)}.
629a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     *
630a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * @param child child view to retrieve from
631a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * @param out rect to set to the outpur values
632a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     */
633a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    void getLastChildRect(View child, Rect out) {
634a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final LayoutParams lp = (LayoutParams) child.getLayoutParams();
635a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        out.set(lp.getLastChildRect());
636a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
637a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
638a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    /**
639a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * Get the position rect for the given child. If the child has currently requested layout
640a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * or has a visibility of GONE.
641a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     *
642a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * @param child child view to check
643a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * @param transform true to include transformation in the output rect, false to
644a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     *                        only account for the base position
645a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * @param out rect to set to the output values
646a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     */
647a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    void getChildRect(View child, boolean transform, Rect out) {
648a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        if (child.isLayoutRequested() || child.getVisibility() == View.GONE) {
649a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            out.set(0, 0, 0, 0);
650a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            return;
651a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
652a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        if (transform) {
653a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            getDescendantRect(child, out);
654a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        } else {
655a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            out.set(child.getLeft(), child.getTop(), child.getRight(), child.getBottom());
656a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
657a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
658a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
659a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    /**
660a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * Calculate the desired child rect relative to an anchor rect, respecting both
661a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * gravity and anchorGravity.
662a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     *
663a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * @param child child view to calculate a rect for
664a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * @param layoutDirection the desired layout direction for the CoordinatorLayout
665a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * @param anchorRect rect in CoordinatorLayout coordinates of the anchor view area
666a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * @param out rect to set to the output values
667a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     */
668a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    void getDesiredAnchoredChildRect(View child, int layoutDirection, Rect anchorRect, Rect out) {
669a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final LayoutParams lp = (LayoutParams) child.getLayoutParams();
670a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final int absGravity = GravityCompat.getAbsoluteGravity(
671a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                resolveAnchoredChildGravity(lp.gravity), layoutDirection);
672a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final int absAnchorGravity = GravityCompat.getAbsoluteGravity(
673a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                resolveGravity(lp.anchorGravity),
674a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                layoutDirection);
675a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
676a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final int hgrav = absGravity & Gravity.HORIZONTAL_GRAVITY_MASK;
677a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final int vgrav = absGravity & Gravity.VERTICAL_GRAVITY_MASK;
678a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final int anchorHgrav = absAnchorGravity & Gravity.HORIZONTAL_GRAVITY_MASK;
679a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final int anchorVgrav = absAnchorGravity & Gravity.VERTICAL_GRAVITY_MASK;
680a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
681a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final int childWidth = child.getMeasuredWidth();
682a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final int childHeight = child.getMeasuredHeight();
683a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
684a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        int left;
685a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        int top;
686a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
687a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        // Align to the anchor
688a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        switch (anchorHgrav) {
689a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            default:
690a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            case Gravity.LEFT:
691a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                left = anchorRect.left;
692a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                break;
693a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            case Gravity.RIGHT:
694a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                left = anchorRect.right - childWidth;
695a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                break;
696a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            case Gravity.CENTER_HORIZONTAL:
697a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                left = anchorRect.left + (anchorRect.width() - childWidth) / 2;
698a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                break;
699a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
700a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
701a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        switch (anchorVgrav) {
702a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            default:
703a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            case Gravity.TOP:
704a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                top = anchorRect.top;
705a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                break;
706a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            case Gravity.BOTTOM:
707a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                top = anchorRect.bottom - childHeight;
708a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                break;
709a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            case Gravity.CENTER_VERTICAL:
710a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                top = anchorRect.top + (anchorRect.height() - childHeight) / 2;
711a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                break;
712a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
713a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
714a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        // Offset by the child view's gravity itself
715a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        switch (hgrav) {
716a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            default:
717a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            case Gravity.LEFT:
718a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                // Do nothing, we're already in position.
719a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                break;
720a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            case Gravity.RIGHT:
721a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                left += childWidth;
722a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                break;
723a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            case Gravity.CENTER_HORIZONTAL:
724a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                left += childWidth / 2;
725a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                break;
726a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
727a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
728a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        switch (vgrav) {
729a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            default:
730a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            case Gravity.TOP:
731a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                // Do nothing, we're already in position.
732a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                break;
733a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            case Gravity.BOTTOM:
734a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                top += childHeight;
735a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                break;
736a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            case Gravity.CENTER_VERTICAL:
737a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                top += childHeight / 2;
738a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                break;
739a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
740a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
741a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final int width = getWidth();
742a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final int height = getHeight();
743a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
744a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        // Obey margins and padding
745a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        left = Math.max(getPaddingLeft() + lp.leftMargin,
746a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                Math.min(left,
747a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                        width - getPaddingRight() - childWidth - lp.rightMargin));
748a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        top = Math.max(getPaddingTop() + lp.topMargin,
749a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                Math.min(top,
750a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                        height - getPaddingBottom() - childHeight - lp.bottomMargin));
751a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
752a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        out.set(left, top, left + childWidth, top + childHeight);
753a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
754a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
755a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    /**
756a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * CORE ASSUMPTION: anchor has been laid out by the time this is called for a given child view.
757a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     *
758a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * @param child child to lay out
759a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * @param anchor view to anchor child relative to; already laid out.
760a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * @param layoutDirection ViewCompat constant for layout direction
761a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     */
762a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    private void layoutChildWithAnchor(View child, View anchor, int layoutDirection) {
763a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final LayoutParams lp = (LayoutParams) child.getLayoutParams();
764a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
765a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final Rect anchorRect = mTempRect1;
766a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final Rect childRect = mTempRect2;
767a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        getDescendantRect(anchor, anchorRect);
768a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        getDesiredAnchoredChildRect(child, layoutDirection, anchorRect, childRect);
769a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
770a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        child.layout(childRect.left, childRect.top, childRect.right, childRect.bottom);
771a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
772a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
773a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    /**
774a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * Lay out a child view with respect to a keyline.
775a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     *
776a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * <p>The keyline represents a horizontal offset from the unpadded starting edge of
777a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * the CoordinatorLayout. The child's gravity will affect how it is positioned with
778a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * respect to the keyline.</p>
779a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     *
780a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * @param child child to lay out
781a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * @param keyline offset from the starting edge in pixels of the keyline to align with
782a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * @param layoutDirection ViewCompat constant for layout direction
783a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     */
784a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    private void layoutChildWithKeyline(View child, int keyline, int layoutDirection) {
785a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final LayoutParams lp = (LayoutParams) child.getLayoutParams();
786a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final int absGravity = GravityCompat.getAbsoluteGravity(
787a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                resolveKeylineGravity(lp.gravity), layoutDirection);
788a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
789a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final int hgrav = absGravity & Gravity.HORIZONTAL_GRAVITY_MASK;
790a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final int vgrav = absGravity & Gravity.VERTICAL_GRAVITY_MASK;
791a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final int width = getWidth();
792a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final int height = getHeight();
793a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final int childWidth = child.getMeasuredWidth();
794a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final int childHeight = child.getMeasuredHeight();
795a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
796a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        if (layoutDirection == ViewCompat.LAYOUT_DIRECTION_RTL) {
797a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            keyline = width - keyline;
798a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
799a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
800a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        int left = getKeyline(keyline) - childWidth;
801a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        int top = 0;
802a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
803a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        switch (hgrav) {
804a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            default:
805a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            case Gravity.LEFT:
806a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                // Nothing to do.
807a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                break;
808a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            case Gravity.RIGHT:
809a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                left += childWidth;
810a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                break;
811a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            case Gravity.CENTER_HORIZONTAL:
812a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                left += childWidth / 2;
813a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                break;
814a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
815a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
816a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        switch (vgrav) {
817a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            default:
818a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            case Gravity.TOP:
819a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                // Do nothing, we're already in position.
820a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                break;
821a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            case Gravity.BOTTOM:
822a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                top += childHeight;
823a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                break;
824a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            case Gravity.CENTER_VERTICAL:
825a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                top += childHeight / 2;
826a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                break;
827a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
828a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
829a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        // Obey margins and padding
830a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        left = Math.max(getPaddingLeft() + lp.leftMargin,
831a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                Math.min(left,
832a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                        width - getPaddingRight() - childWidth - lp.rightMargin));
833a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        top = Math.max(getPaddingTop() + lp.topMargin,
834a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                Math.min(top,
835a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                        height - getPaddingBottom() - childHeight - lp.bottomMargin));
836a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
837a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        child.layout(left, top, left + childWidth, top + childHeight);
838a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
839a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
840a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    /**
841a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * Lay out a child view with no special handling. This will position the child as
842a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * if it were within a FrameLayout or similar simple frame.
843a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     *
844a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * @param child child view to lay out
845a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * @param layoutDirection ViewCompat constant for the desired layout direction
846a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     */
847a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    private void layoutChild(View child, int layoutDirection) {
848a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final LayoutParams lp = (LayoutParams) child.getLayoutParams();
849a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final Rect parent = mTempRect1;
850a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        parent.set(getPaddingLeft() + lp.leftMargin,
851a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                getPaddingTop() + lp.topMargin,
852a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                getWidth() - getPaddingRight() - lp.rightMargin,
853a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                getHeight() - getPaddingBottom() - lp.bottomMargin);
854a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final Rect out = mTempRect2;
855a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        GravityCompat.apply(resolveGravity(lp.gravity), child.getMeasuredWidth(),
856a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                child.getMeasuredHeight(), parent, out, layoutDirection);
857a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        child.layout(out.left, out.top, out.right, out.bottom);
858a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
859a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
860a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    /**
861a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * Return the given gravity value or the default if the passed value is NO_GRAVITY.
862a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * This should be used for children that are not anchored to another view or a keyline.
863a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     */
864a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    private static int resolveGravity(int gravity) {
865a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        return gravity == Gravity.NO_GRAVITY ? GravityCompat.START | Gravity.TOP : gravity;
866a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
867a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
868a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    /**
869a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * Return the given gravity value or the default if the passed value is NO_GRAVITY.
870a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * This should be used for children that are positioned relative to a keyline.
871a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     */
872a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    private static int resolveKeylineGravity(int gravity) {
873a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        return gravity == Gravity.NO_GRAVITY ? GravityCompat.END | Gravity.TOP : gravity;
874a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
875a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
876a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    /**
877a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * Return the given gravity value or the default if the passed value is NO_GRAVITY.
878a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * This should be used for children that are anchored to another view.
879a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     */
880a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    private static int resolveAnchoredChildGravity(int gravity) {
881a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        return gravity == Gravity.NO_GRAVITY ? Gravity.CENTER : gravity;
882a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
883a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
884a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    @Override
885a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
886a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final LayoutParams lp = (LayoutParams) child.getLayoutParams();
887a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        if (lp.mBehavior != null && lp.mBehavior.getScrimOpacity(this, child) > 0.f) {
888a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            if (mScrimPaint == null) {
889a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                mScrimPaint = new Paint();
890a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            }
891a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            mScrimPaint.setColor(lp.mBehavior.getScrimColor(this, child));
892a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
893a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            // TODO: Set the clip appropriately to avoid unnecessary overdraw.
894a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            canvas.drawRect(getPaddingLeft(), getPaddingTop(),
895a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                    getWidth() - getPaddingRight(), getHeight() - getPaddingBottom(), mScrimPaint);
896a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
897a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        return super.drawChild(canvas, child, drawingTime);
898a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
899a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
900a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    /**
901a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     * Dispatch any dependent view changes to the relevant {@link Behavior} instances.
902a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     *
903a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     * Usually run as part of the pre-draw step when at least one child view has a reported
904a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * dependency on another view. This allows CoordinatorLayout to account for layout
905a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * changes and animations that occur outside of the normal layout pass.
906a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     *
907a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     * It can also be ran as part of the nested scrolling dispatch to ensure that any offsetting
908a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     * is completed within the correct coordinate window.
909a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     *
910a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * The offsetting behavior implemented here does not store the computed offset in
911a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * the LayoutParams; instead it expects that the layout process will always reconstruct
912a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * the proper positioning.
913a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     *
914a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     * @param fromNestedScroll true if this is being called from one of the nested scroll methods,
915a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     *                         false if run as part of the pre-draw step.
916a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     */
917a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    void dispatchOnDependentViewChanged(final boolean fromNestedScroll) {
918a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final int layoutDirection = ViewCompat.getLayoutDirection(this);
919a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final int childCount = mDependencySortedChildren.size();
920a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        for (int i = 0; i < childCount; i++) {
921a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            final View child = mDependencySortedChildren.get(i);
922a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
923a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
924a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            // Check child views before for anchor
925a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            for (int j = 0; j < i; j++) {
926a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                final View checkChild = mDependencySortedChildren.get(j);
927a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
928a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                if (lp.mAnchorDirectChild == checkChild) {
929a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                    offsetChildToAnchor(child, layoutDirection);
930a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                }
931a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            }
932a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
933a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            // Did it change? if not continue
934a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            final Rect oldRect = mTempRect1;
935a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            final Rect newRect = mTempRect2;
936a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            getLastChildRect(child, oldRect);
937b7f9224b1495db47eb8fd813b5912250e900770aChris Banes            getChildRect(child, true, newRect);
938a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            if (oldRect.equals(newRect)) {
939a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                continue;
940a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            }
941a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            recordLastChildRect(child, newRect);
942a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
943a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            // Update any behavior-dependent views for the change
944a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            for (int j = i + 1; j < childCount; j++) {
945a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                final View checkChild = mDependencySortedChildren.get(j);
946a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                final LayoutParams checkLp = (LayoutParams) checkChild.getLayoutParams();
947a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                final Behavior b = checkLp.getBehavior();
948a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
949a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                if (b != null && b.layoutDependsOn(this, checkChild, child)) {
950a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes                    if (!fromNestedScroll && checkLp.getChangedAfterNestedScroll()) {
951a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes                        // If this is not from a nested scroll and we have already been changed
952a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes                        // from a nested scroll, skip the dispatch and reset the flag
953a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes                        checkLp.resetChangedAfterNestedScroll();
954a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes                        continue;
955a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes                    }
956a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
957a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes                    final boolean handled = b.onDependentViewChanged(this, checkChild, child);
958a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
959a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes                    if (fromNestedScroll) {
960a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes                        // If this is from a nested scroll, set the flag so that we may skip
961a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes                        // any resulting onPreDraw dispatch (if needed)
962a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes                        checkLp.setChangedAfterNestedScroll(handled);
963a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes                    }
964a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes                }
965a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes            }
966a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        }
967a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    }
968a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
969a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    /**
970a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     * Allows the caller to manually dispatch
971a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     * {@link Behavior#onDependentViewChanged(CoordinatorLayout, View, View)} to the associated
972a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     * {@link Behavior} instances of views which depend on the provided {@link View}.
973a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     *
974a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     * <p>You should not normally need to call this method as the it will be automatically done
975a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     * when the view has changed.
976a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     *
977a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     * @param view the View to find dependents of to dispatch the call.
978a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     */
979a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    public void dispatchDependentViewsChanged(View view) {
980a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        final int childCount = mDependencySortedChildren.size();
981a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        boolean viewSeen = false;
982a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        for (int i = 0; i < childCount; i++) {
983a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes            final View child = mDependencySortedChildren.get(i);
984a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes            if (child == view) {
985a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes                // We've seen our view, which means that any Views after this could be dependent
986a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes                viewSeen = true;
987a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes                continue;
988a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes            }
989a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes            if (viewSeen) {
990a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes                CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams)
991a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes                        child.getLayoutParams();
992a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes                CoordinatorLayout.Behavior b = lp.getBehavior();
993a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes                if (b != null && lp.dependsOn(this, child, view)) {
994a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes                    b.onDependentViewChanged(this, child, view);
995a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                }
996a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            }
997a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
998a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
999a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1000a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    /**
1001a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     * Returns the list of views which the provided view depends on. Do not store this list as it's
1002a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     * contents may not be valid beyond the caller.
1003a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     *
1004a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     * @param child the view to find dependencies for.
1005a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     *
1006a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     * @return the list of views which {@code child} depends on.
1007a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes     */
1008a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    public List<View> getDependencies(View child) {
1009a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        // TODO The result of this is probably a good candidate for caching
1010a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
1011a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        final LayoutParams lp = (LayoutParams) child.getLayoutParams();
1012a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        final List<View> list = mTempDependenciesList;
1013a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        list.clear();
1014a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
1015a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        final int childCount = getChildCount();
1016a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        for (int i = 0; i < childCount; i++) {
1017a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes            final View other = getChildAt(i);
1018a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes            if (other == child) {
1019a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes                continue;
1020a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes            }
1021a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes            if (lp.dependsOn(this, child, other)) {
1022a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes                list.add(other);
1023a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes            }
1024a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        }
1025a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
1026a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        return list;
1027a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    }
1028a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
1029a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes    /**
1030a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * Add or remove the pre-draw listener as necessary.
1031a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     */
1032a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    void ensurePreDrawListener() {
1033a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        boolean hasDependencies = false;
1034a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final int childCount = getChildCount();
1035a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        for (int i = 0; i < childCount; i++) {
1036a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            final View child = getChildAt(i);
1037a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            if (hasDependencies(child)) {
1038a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                hasDependencies = true;
1039a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                break;
1040a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            }
1041a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
1042a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1043a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        if (hasDependencies != mNeedsPreDrawListener) {
1044a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            if (hasDependencies) {
1045a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                addPreDrawListener();
1046a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            } else {
1047a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                removePreDrawListener();
1048a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            }
1049a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
1050a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
1051a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1052a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    /**
1053a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * Check if the given child has any layout dependencies on other child views.
1054a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     */
1055a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    boolean hasDependencies(View child) {
1056a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final LayoutParams lp = (LayoutParams) child.getLayoutParams();
1057a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        if (lp.mAnchorView != null) {
1058a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            return true;
1059a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
1060a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1061a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final int childCount = getChildCount();
1062a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        for (int i = 0; i < childCount; i++) {
1063a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            final View other = getChildAt(i);
1064a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            if (other == child) {
1065a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                continue;
1066a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            }
1067a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            if (lp.dependsOn(this, child, other)) {
1068a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                return true;
1069a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            }
1070a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
1071a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        return false;
1072a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
1073a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1074a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    /**
1075a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * Add the pre-draw listener if we're attached to a window and mark that we currently
1076a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * need it when attached.
1077a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     */
1078a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    void addPreDrawListener() {
1079a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        if (mIsAttachedToWindow) {
1080a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            // Add the listener
1081a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            if (mOnPreDrawListener == null) {
1082a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                mOnPreDrawListener = new OnPreDrawListener();
1083a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            }
1084a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            final ViewTreeObserver vto = getViewTreeObserver();
1085a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            vto.addOnPreDrawListener(mOnPreDrawListener);
1086a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
1087a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1088a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        // Record that we need the listener regardless of whether or not we're attached.
1089a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        // We'll add the real listener when we become attached.
1090a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        mNeedsPreDrawListener = true;
1091a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
1092a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1093a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    /**
1094a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * Remove the pre-draw listener if we're attached to a window and mark that we currently
1095a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * do not need it when attached.
1096a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     */
1097a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    void removePreDrawListener() {
1098a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        if (mIsAttachedToWindow) {
1099a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            if (mOnPreDrawListener != null) {
1100a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                final ViewTreeObserver vto = getViewTreeObserver();
1101a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                vto.removeOnPreDrawListener(mOnPreDrawListener);
1102a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            }
1103a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
1104a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        mNeedsPreDrawListener = false;
1105a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
1106a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1107a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    /**
1108a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * Adjust the child left, top, right, bottom rect to the correct anchor view position,
1109a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * respecting gravity and anchor gravity.
1110a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     *
1111a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * Note that child translation properties are ignored in this process, allowing children
1112a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * to be animated away from their anchor. However, if the anchor view is animated,
1113a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * the child will be offset to match the anchor's translated position.
1114a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     */
1115a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    void offsetChildToAnchor(View child, int layoutDirection) {
1116a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final LayoutParams lp = (LayoutParams) child.getLayoutParams();
1117a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        if (lp.mAnchorView != null) {
1118a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            final Rect anchorRect = mTempRect1;
1119a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            final Rect childRect = mTempRect2;
1120a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            final Rect desiredChildRect = mTempRect3;
1121a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1122a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            getDescendantRect(lp.mAnchorView, anchorRect);
1123a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            getChildRect(child, false, childRect);
1124a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            getDesiredAnchoredChildRect(child, layoutDirection, anchorRect, desiredChildRect);
1125a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1126a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            final int dx = desiredChildRect.left - childRect.left;
1127a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            final int dy = desiredChildRect.top - childRect.top;
1128a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1129a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            if (dx != 0) {
1130a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                child.offsetLeftAndRight(dx);
1131a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            }
1132a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            if (dy != 0) {
1133a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                child.offsetTopAndBottom(dy);
1134a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            }
1135a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
1136a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes            if (dx != 0 || dy != 0) {
1137a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes                // If we have needed to move, make sure to notify the child's Behavior
1138a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes                final Behavior b = lp.getBehavior();
1139a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes                if (b != null) {
1140a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes                    b.onDependentViewChanged(this, child, lp.mAnchorView);
1141a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes                }
1142a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes            }
1143a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
1144a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
1145a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1146a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    /**
1147a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * Check if a given point in the CoordinatorLayout's coordinates are within the view bounds
1148a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * of the given direct child view.
1149a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     *
1150a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * @param child child view to test
1151a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * @param x X coordinate to test, in the CoordinatorLayout's coordinate system
1152a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * @param y Y coordinate to test, in the CoordinatorLayout's coordinate system
1153a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * @return true if the point is within the child view's bounds, false otherwise
1154a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     */
1155a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    public boolean isPointInChildBounds(View child, int x, int y) {
1156a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final Rect r = mTempRect1;
1157a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        getDescendantRect(child, r);
1158a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        return r.contains(x, y);
1159a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
1160a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1161b7f9224b1495db47eb8fd813b5912250e900770aChris Banes    /**
1162b7f9224b1495db47eb8fd813b5912250e900770aChris Banes     * Check whether two views overlap each other. The views need to be descendants of this
1163b7f9224b1495db47eb8fd813b5912250e900770aChris Banes     * {@link CoordinatorLayout} in the view hierarchy.
1164b7f9224b1495db47eb8fd813b5912250e900770aChris Banes     *
1165b7f9224b1495db47eb8fd813b5912250e900770aChris Banes     * @param first first child view to test
1166b7f9224b1495db47eb8fd813b5912250e900770aChris Banes     * @param second second child view to test
1167b7f9224b1495db47eb8fd813b5912250e900770aChris Banes     * @return true if both views are visible and overlap each other
1168b7f9224b1495db47eb8fd813b5912250e900770aChris Banes     */
1169b7f9224b1495db47eb8fd813b5912250e900770aChris Banes    public boolean doViewsOverlap(View first, View second) {
1170b7f9224b1495db47eb8fd813b5912250e900770aChris Banes        if (first.getVisibility() == VISIBLE && second.getVisibility() == VISIBLE) {
1171b7f9224b1495db47eb8fd813b5912250e900770aChris Banes            final Rect firstRect = mTempRect1;
1172b7f9224b1495db47eb8fd813b5912250e900770aChris Banes            getChildRect(first, first.getParent() != this, firstRect);
1173b7f9224b1495db47eb8fd813b5912250e900770aChris Banes            final Rect secondRect = mTempRect2;
1174b7f9224b1495db47eb8fd813b5912250e900770aChris Banes            getChildRect(second, second.getParent() != this, secondRect);
1175b7f9224b1495db47eb8fd813b5912250e900770aChris Banes
1176b7f9224b1495db47eb8fd813b5912250e900770aChris Banes            return !(firstRect.left > secondRect.right || firstRect.top > secondRect.bottom
1177b7f9224b1495db47eb8fd813b5912250e900770aChris Banes                    || firstRect.right < secondRect.left || firstRect.bottom < secondRect.top);
1178b7f9224b1495db47eb8fd813b5912250e900770aChris Banes        }
1179b7f9224b1495db47eb8fd813b5912250e900770aChris Banes        return false;
1180b7f9224b1495db47eb8fd813b5912250e900770aChris Banes    }
1181b7f9224b1495db47eb8fd813b5912250e900770aChris Banes
1182a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    @Override
1183a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    public LayoutParams generateLayoutParams(AttributeSet attrs) {
1184a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        return new LayoutParams(getContext(), attrs);
1185a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
1186a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1187a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    @Override
1188a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
1189a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        if (p instanceof LayoutParams) {
1190a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            return new LayoutParams((LayoutParams) p);
1191a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        } else if (p instanceof MarginLayoutParams) {
1192a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            return new LayoutParams((MarginLayoutParams) p);
1193a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
1194a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        return new LayoutParams(p);
1195a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
1196a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1197a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    @Override
1198a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    protected LayoutParams generateDefaultLayoutParams() {
1199a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
1200a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
1201a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1202a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    @Override
1203a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
1204a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        return p instanceof LayoutParams && super.checkLayoutParams(p);
1205a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
1206a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1207a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) {
12085cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        boolean handled = false;
12095cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell
12105cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        final int childCount = getChildCount();
12115cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        for (int i = 0; i < childCount; i++) {
12125cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            final View view = getChildAt(i);
12135cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            final LayoutParams lp = (LayoutParams) view.getLayoutParams();
12145cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            final Behavior viewBehavior = lp.getBehavior();
12155cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            if (viewBehavior != null) {
12165cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell                final boolean accepted = viewBehavior.onStartNestedScroll(this, view, child, target,
12175cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell                        nestedScrollAxes);
12185cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell                handled |= accepted;
12195cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell
12205cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell                lp.acceptNestedScroll(accepted);
12215cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            } else {
12225cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell                lp.acceptNestedScroll(false);
12235cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            }
12245cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        }
12255cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        return handled;
1226a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
1227a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1228a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    public void onNestedScrollAccepted(View child, View target, int nestedScrollAxes) {
1229a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        mNestedScrollingParentHelper.onNestedScrollAccepted(child, target, nestedScrollAxes);
12305cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        mNestedScrollingDirectChild = child;
12315cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        mNestedScrollingTarget = target;
12325cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell
12335cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        final int childCount = getChildCount();
12345cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        for (int i = 0; i < childCount; i++) {
12355cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            final View view = getChildAt(i);
12365cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            final LayoutParams lp = (LayoutParams) view.getLayoutParams();
12375cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            if (!lp.isNestedScrollAccepted()) {
12385cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell                continue;
12395cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            }
12405cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell
12415cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            final Behavior viewBehavior = lp.getBehavior();
12425cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            if (viewBehavior != null) {
12435cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell                viewBehavior.onNestedScrollAccepted(this, view, child, target, nestedScrollAxes);
12445cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            }
12455cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        }
1246a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
1247a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1248a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    public void onStopNestedScroll(View target) {
1249a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        mNestedScrollingParentHelper.onStopNestedScroll(target);
12505cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell
12515cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        final int childCount = getChildCount();
12525cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        for (int i = 0; i < childCount; i++) {
12535cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            final View view = getChildAt(i);
12545cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            final LayoutParams lp = (LayoutParams) view.getLayoutParams();
12555cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            if (!lp.isNestedScrollAccepted()) {
12565cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell                continue;
12575cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            }
12585cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell
12595cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            final Behavior viewBehavior = lp.getBehavior();
12605cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            if (viewBehavior != null) {
12615cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell                viewBehavior.onStopNestedScroll(this, view, target);
12625cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            }
12635cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            lp.resetNestedScroll();
1264a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes            lp.resetChangedAfterNestedScroll();
12655cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        }
12665cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell
12675cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        mNestedScrollingDirectChild = null;
12685cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        mNestedScrollingTarget = null;
1269a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
1270a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1271a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    public void onNestedScroll(View target, int dxConsumed, int dyConsumed,
1272a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            int dxUnconsumed, int dyUnconsumed) {
12735cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        final int childCount = getChildCount();
1274a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        boolean accepted = false;
1275a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
12765cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        for (int i = 0; i < childCount; i++) {
12775cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            final View view = getChildAt(i);
12785cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            final LayoutParams lp = (LayoutParams) view.getLayoutParams();
12795cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            if (!lp.isNestedScrollAccepted()) {
12805cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell                continue;
12815cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            }
12825cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell
12835cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            final Behavior viewBehavior = lp.getBehavior();
12845cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            if (viewBehavior != null) {
12855cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell                viewBehavior.onNestedScroll(this, view, target, dxConsumed, dyConsumed,
12865cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell                        dxUnconsumed, dyUnconsumed);
1287a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes                accepted = true;
12885cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            }
12895cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        }
1290a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
1291a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        if (accepted) {
1292a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes            dispatchOnDependentViewChanged(true);
1293a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        }
1294a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
1295a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1296a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) {
12975cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        int xConsumed = 0;
12985cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        int yConsumed = 0;
1299a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        boolean accepted = false;
13005cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell
13015cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        final int childCount = getChildCount();
13025cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        for (int i = 0; i < childCount; i++) {
13035cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            final View view = getChildAt(i);
13045cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            final LayoutParams lp = (LayoutParams) view.getLayoutParams();
13055cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            if (!lp.isNestedScrollAccepted()) {
13065cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell                continue;
13075cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            }
13085cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell
13095cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            final Behavior viewBehavior = lp.getBehavior();
13105cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            if (viewBehavior != null) {
13115cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell                mTempIntPair[0] = mTempIntPair[1] = 0;
13125cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell                viewBehavior.onNestedPreScroll(this, view, target, dx, dy, mTempIntPair);
13135cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell
13145cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell                xConsumed = dx > 0 ? Math.max(xConsumed, mTempIntPair[0])
13155cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell                        : Math.min(xConsumed, mTempIntPair[0]);
13165cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell                yConsumed = dy > 0 ? Math.max(yConsumed, mTempIntPair[1])
13175cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell                        : Math.min(yConsumed, mTempIntPair[1]);
1318a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
1319a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes                accepted = true;
13205cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            }
13215cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        }
13225cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell
13235cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        consumed[0] = xConsumed;
13245cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        consumed[1] = yConsumed;
1325a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
1326a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        if (accepted) {
1327a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes            dispatchOnDependentViewChanged(true);
1328a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        }
1329a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
1330a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1331a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) {
13325cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        boolean handled = false;
13335cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell
13345cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        final int childCount = getChildCount();
13355cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        for (int i = 0; i < childCount; i++) {
13365cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            final View view = getChildAt(i);
13375cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            final LayoutParams lp = (LayoutParams) view.getLayoutParams();
13385cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            if (!lp.isNestedScrollAccepted()) {
13395cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell                continue;
13405cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            }
13415cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell
13425cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            final Behavior viewBehavior = lp.getBehavior();
13435cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            if (viewBehavior != null) {
13445cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell                handled |= viewBehavior.onNestedFling(this, view, target, velocityX, velocityY,
13455cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell                        consumed);
13465cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            }
13475cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        }
1348a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        if (handled) {
1349a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes            dispatchOnDependentViewChanged(true);
1350a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        }
13515cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        return handled;
1352a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
1353a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1354a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    public boolean onNestedPreFling(View target, float velocityX, float velocityY) {
13555cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        boolean handled = false;
13565cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell
13575cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        final int childCount = getChildCount();
13585cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        for (int i = 0; i < childCount; i++) {
13595cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            final View view = getChildAt(i);
13605cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            final LayoutParams lp = (LayoutParams) view.getLayoutParams();
13615cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            if (!lp.isNestedScrollAccepted()) {
13625cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell                continue;
13635cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            }
13645cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell
13655cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            final Behavior viewBehavior = lp.getBehavior();
13665cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            if (viewBehavior != null) {
13675cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell                handled |= viewBehavior.onNestedPreFling(this, view, target, velocityX, velocityY);
13685cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            }
13695cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        }
13705cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        return handled;
1371a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
1372a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1373a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    public int getNestedScrollAxes() {
1374a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        return mNestedScrollingParentHelper.getNestedScrollAxes();
1375a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
1376a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1377a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    class OnPreDrawListener implements ViewTreeObserver.OnPreDrawListener {
1378a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        @Override
1379a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        public boolean onPreDraw() {
1380a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes            dispatchOnDependentViewChanged(false);
1381a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            return true;
1382a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
1383a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
1384a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1385a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    /**
1386a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * Sorts child views with higher Z values to the beginning of a collection.
1387a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     */
1388a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    static class ViewElevationComparator implements Comparator<View> {
1389a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        @Override
1390a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        public int compare(View lhs, View rhs) {
1391a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            final float lz = ViewCompat.getZ(lhs);
1392a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            final float rz = ViewCompat.getZ(rhs);
1393a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            if (lz > rz) {
1394a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                return -1;
1395a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            } else if (lz < rz) {
1396a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                return 1;
1397a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            }
1398a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            return 0;
1399a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
1400a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
1401a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1402a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    /**
1403a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * Defines the default {@link Behavior} of a {@link View} class.
1404a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     *
1405a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * <p>When writing a custom view, use this annotation to define the default behavior
1406a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * when used as a direct child of an {@link CoordinatorLayout}. The default behavior
1407a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * can be overridden using {@link LayoutParams#setBehavior}.</p>
1408a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     *
1409a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * <p>Example: <code>@DefaultBehavior(MyBehavior.class)</code></p>
1410a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     */
1411a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    @Retention(RetentionPolicy.RUNTIME)
1412a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    public @interface DefaultBehavior {
1413a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        Class<? extends Behavior> value();
1414a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
1415a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1416a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    /**
1417a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * Interaction behavior plugin for child views of {@link CoordinatorLayout}.
1418a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     *
1419a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * <p>A Behavior implements one or more interactions that a user can take on a child view.
1420a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * These interactions may include drags, swipes, flings, or any other gestures.</p>
1421a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     *
1422a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * @param <V> The View type that this Behavior operates on
1423a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     */
1424a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    public static abstract class Behavior<V extends View> {
1425a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1426a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        /**
1427a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * Default constructor for instantiating Behaviors.
1428a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         */
1429a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        public Behavior() {
1430a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
1431a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1432a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        /**
1433a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * Default constructor for inflating Behaviors from layout. The Behavior will have
1434a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * the opportunity to parse specially defined layout parameters. These parameters will
1435a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * appear on the child view tag.
1436a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *
1437a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param context
1438a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param attrs
1439a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         */
1440a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        public Behavior(Context context, AttributeSet attrs) {
1441a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
1442a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1443a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        /**
1444a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * Respond to CoordinatorLayout touch events before they are dispatched to child views.
1445a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *
1446a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * <p>Behaviors can use this to monitor inbound touch events until one decides to
1447a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * intercept the rest of the event stream to take an action on its associated child view.
1448a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * This method will return false until it detects the proper intercept conditions, then
1449a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * return true once those conditions have occurred.</p>
1450a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *
1451a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * <p>Once a Behavior intercepts touch events, the rest of the event stream will
1452a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * be sent to the {@link #onTouchEvent} method.</p>
1453a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *
1454a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * <p>The default implementation of this method always returns false.</p>
1455a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *
1456a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param parent the parent view currently receiving this touch event
1457a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param child the child view associated with this Behavior
1458a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param ev the MotionEvent describing the touch event being processed
1459a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @return true if this Behavior would like to intercept and take over the event stream.
1460a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *         The default always returns false.
1461a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         */
1462a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        public boolean onInterceptTouchEvent(CoordinatorLayout parent, V child, MotionEvent ev) {
1463a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            return false;
1464a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
1465a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1466a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        /**
1467a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * Respond to CoordinatorLayout touch events after this Behavior has started
1468a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * {@link #onInterceptTouchEvent intercepting} them.
1469a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *
1470a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * <p>Behaviors may intercept touch events in order to help the CoordinatorLayout
1471a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * manipulate its child views. For example, a Behavior may allow a user to drag a
1472a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * UI pane open or closed. This method should perform actual mutations of view
1473a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * layout state.</p>
1474a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *
1475a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param parent the parent view currently receiving this touch event
1476a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param child the child view associated with this Behavior
1477a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param ev the MotionEvent describing the touch event being processed
1478a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @return true if this Behavior handled this touch event and would like to continue
1479a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *         receiving events in this stream. The default always returns false.
1480a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         */
1481a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        public boolean onTouchEvent(CoordinatorLayout parent, V child, MotionEvent ev) {
1482a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            return false;
1483a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
1484a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1485a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        /**
1486a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * Supply a scrim color that will be painted behind the associated child view.
1487a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *
1488a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * <p>A scrim may be used to indicate that the other elements beneath it are not currently
1489a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * interactive or actionable, drawing user focus and attention to the views above the scrim.
1490a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * </p>
1491a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *
1492a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * <p>The default implementation returns {@link Color#BLACK}.</p>
1493a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *
1494a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param parent the parent view of the given child
1495a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param child the child view above the scrim
1496a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @return the desired scrim color in 0xAARRGGBB format. The default return value is
1497a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *         {@link Color#BLACK}.
1498a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @see #getScrimOpacity(CoordinatorLayout, android.view.View)
1499a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         */
1500a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        public final int getScrimColor(CoordinatorLayout parent, V child) {
1501a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            return Color.BLACK;
1502a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
1503a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1504a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        /**
1505a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * Determine the current opacity of the scrim behind a given child view
1506a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *
1507a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * <p>A scrim may be used to indicate that the other elements beneath it are not currently
1508a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * interactive or actionable, drawing user focus and attention to the views above the scrim.
1509a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * </p>
1510a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *
1511a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * <p>The default implementation returns 0.0f.</p>
1512a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *
1513a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param parent the parent view of the given child
1514a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param child the child view above the scrim
1515a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @return the desired scrim opacity from 0.0f to 1.0f. The default return value is 0.0f.
1516a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         */
1517a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        public final float getScrimOpacity(CoordinatorLayout parent, V child) {
1518a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            return 0.f;
1519a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
1520a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1521a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        /**
1522a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * Determine whether interaction with views behind the given child in the child order
1523a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * should be blocked.
1524a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *
1525a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * <p>The default implementation returns true if
1526a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * {@link #getScrimOpacity(CoordinatorLayout, android.view.View)} would return > 0.0f.</p>
1527a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *
1528a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param parent the parent view of the given child
1529a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param child the child view to test
1530a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @return true if {@link #getScrimOpacity(CoordinatorLayout, android.view.View)} would
1531a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *         return > 0.0f.
1532a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         */
1533a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        public boolean blocksInteractionBelow(CoordinatorLayout parent, V child) {
1534a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            return getScrimOpacity(parent, child) > 0.f;
1535a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
1536a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1537a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        /**
1538a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * Determine whether the supplied child view has another specific sibling view as a
1539a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * layout dependency.
1540a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *
1541a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * <p>This method will be called at least once in response to a layout request. If it
1542a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * returns true for a given child and dependency view pair, the parent CoordinatorLayout
1543a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * will:</p>
1544a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * <ol>
1545a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *     <li>Always lay out this child after the dependent child is laid out, regardless
1546a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *     of child order.</li>
1547a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *     <li>Call {@link #onDependentViewChanged} when the dependency view's layout or
1548a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *     position changes.</li>
1549a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * </ol>
1550a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *
1551a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param parent the parent view of the given child
1552a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param child the child view to test
1553a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param dependency the proposed dependency of child
1554a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @return true if child's layout depends on the proposed dependency's layout,
1555a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *         false otherwise
1556a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *
1557a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @see #onDependentViewChanged(CoordinatorLayout, android.view.View, android.view.View)
1558a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         */
1559a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        public boolean layoutDependsOn(CoordinatorLayout parent, V child, View dependency) {
1560a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            return false;
1561a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
1562a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1563a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        /**
1564a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes         * Respond to a change in a child's dependent view
1565a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes         *
1566a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes         * <p>This method is called whenever a dependent view changes in size or position outside
1567a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes         * of the standard layout flow. A Behavior may use this method to appropriately update
1568a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes         * the child view in response.</p>
1569a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *
1570a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes         * <p>A view's dependency is determined by
1571a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes         * {@link #layoutDependsOn(CoordinatorLayout, android.view.View, android.view.View)} or
1572a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes         * if {@code child} has set another view as it's anchor.</p>
1573a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *
1574a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * <p>Note that if a Behavior changes the layout of a child via this method, it should
1575a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * also be able to reconstruct the correct position in
1576a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * {@link #onLayoutChild(CoordinatorLayout, android.view.View, int) onLayoutChild}.
1577a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * <code>onDependentViewChanged</code> will not be called during normal layout since
1578a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * the layout of each child view will always happen in dependency order.</p>
1579a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *
1580a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * <p>If the Behavior changes the child view's size or position, it should return true.
1581a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * The default implementation returns false.</p>
1582a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *
1583a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param parent the parent view of the given child
1584a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param child the child view to manipulate
1585a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param dependency the dependent view that changed
1586a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @return true if the Behavior changed the child view's size or position, false otherwise
1587a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         */
1588a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        public boolean onDependentViewChanged(CoordinatorLayout parent, V child, View dependency) {
1589a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            return false;
1590a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
1591a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1592a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        /**
1593a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * Determine whether the given child view should be considered dirty.
1594a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *
1595a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * <p>If a property determined by the Behavior such as other dependent views would change,
1596a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * the Behavior should report a child view as dirty. This will prompt the CoordinatorLayout
1597a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * to re-query Behavior-determined properties as appropriate.</p>
1598a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *
1599a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param parent the parent view of the given child
1600a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param child the child view to check
1601a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @return true if child is dirty
1602a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         */
1603a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        public boolean isDirty(CoordinatorLayout parent, V child) {
1604a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            return false;
1605a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
1606a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1607a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        /**
1608a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * Called when the parent CoordinatorLayout is about to measure the given child view.
1609a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *
1610a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * <p>This method can be used to perform custom or modified measurement of a child view
1611a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * in place of the default child measurement behavior. The Behavior's implementation
1612a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * can delegate to the standard CoordinatorLayout measurement behavior by calling
1613a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * {@link CoordinatorLayout#onMeasureChild(android.view.View, int, int, int, int)
1614a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * parent.onMeasureChild}.</p>
1615a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *
1616a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param parent the parent CoordinatorLayout
1617a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param child the child to measure
1618a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param parentWidthMeasureSpec the width requirements for this view
1619a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param widthUsed extra space that has been used up by the parent
1620a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *        horizontally (possibly by other children of the parent)
1621a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param parentHeightMeasureSpec the height requirements for this view
1622a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param heightUsed extra space that has been used up by the parent
1623a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *        vertically (possibly by other children of the parent)
1624a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @return true if the Behavior measured the child view, false if the CoordinatorLayout
1625a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *         should perform its default measurement
1626a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         */
1627a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        public boolean onMeasureChild(CoordinatorLayout parent, V child,
1628a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                int parentWidthMeasureSpec, int widthUsed,
1629a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                int parentHeightMeasureSpec, int heightUsed) {
1630a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            return false;
1631a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
1632a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1633a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        /**
1634a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * Called when the parent CoordinatorLayout is about the lay out the given child view.
1635a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *
1636a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * <p>This method can be used to perform custom or modified layout of a child view
1637a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * in place of the default child layout behavior. The Behavior's implementation can
1638a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * delegate to the standard CoordinatorLayout measurement behavior by calling
1639a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * {@link CoordinatorLayout#onLayoutChild(android.view.View, int)
1640a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * parent.onMeasureChild}.</p>
1641a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *
1642a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * <p>If a Behavior implements
1643a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * {@link #onDependentViewChanged(CoordinatorLayout, android.view.View, android.view.View)}
1644a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * to change the position of a view in response to a dependent view changing, it
1645a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * should also implement <code>onLayoutChild</code> in such a way that respects those
1646a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * dependent views. <code>onLayoutChild</code> will always be called for a dependent view
1647a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * <em>after</em> its dependency has been laid out.</p>
1648a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *
1649a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param parent the parent CoordinatorLayout
1650a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param child child view to lay out
1651a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param layoutDirection the resolved layout direction for the CoordinatorLayout, such as
1652a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *                        {@link ViewCompat#LAYOUT_DIRECTION_LTR} or
1653a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *                        {@link ViewCompat#LAYOUT_DIRECTION_RTL}.
1654a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @return true if the Behavior performed layout of the child view, false to request
1655a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *         default layout behavior
1656a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         */
1657a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        public boolean onLayoutChild(CoordinatorLayout parent, V child, int layoutDirection) {
1658a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            return false;
1659a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
1660a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1661a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        // Utility methods for accessing child-specific, behavior-modifiable properties.
1662a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1663a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        /**
1664a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * Associate a Behavior-specific tag object with the given child view.
1665a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * This object will be stored with the child view's LayoutParams.
1666a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *
1667a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param child child view to set tag with
1668a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param tag tag object to set
1669a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         */
1670a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        public static void setTag(View child, Object tag) {
1671a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
1672a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            lp.mBehaviorTag = tag;
1673a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
1674a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1675a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        /**
1676a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * Get the behavior-specific tag object with the given child view.
1677a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * This object is stored with the child view's LayoutParams.
1678a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *
1679a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param child child view to get tag with
1680a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @return the previously stored tag object
1681a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         */
1682a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        public static Object getTag(View child) {
1683a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
1684a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            return lp.mBehaviorTag;
1685a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
16865cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell
16875cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell
16885cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        /**
16895cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * Called when a descendant of the CoordinatorLayout attempts to initiate a nested scroll.
16905cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         *
16915cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * <p>Any Behavior associated with any direct child of the CoordinatorLayout may respond
16925cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * to this event and return true to indicate that the CoordinatorLayout should act as
16935cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * a nested scrolling parent for this scroll. Only Behaviors that return true from
16945cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * this method will receive subsequent nested scroll events.</p>
16955cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         *
16965cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is
16975cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         *                          associated with
16985cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @param child the child view of the CoordinatorLayout this Behavior is associated with
16995cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @param directTargetChild the child view of the CoordinatorLayout that either is or
17005cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         *                          contains the target of the nested scroll operation
17015cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @param target the descendant view of the CoordinatorLayout initiating the nested scroll
17025cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @param nestedScrollAxes the axes that this nested scroll applies to. See
17035cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         *                         {@link ViewCompat#SCROLL_AXIS_HORIZONTAL},
17045cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         *                         {@link ViewCompat#SCROLL_AXIS_VERTICAL}
17055cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @return true if the Behavior wishes to accept this nested scroll
17065cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         *
17075cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @see NestedScrollingParent#onStartNestedScroll(View, View, int)
17085cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         */
17095cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout,
17105cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell                V child, View directTargetChild, View target, int nestedScrollAxes) {
17115cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            return false;
17125cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        }
17135cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell
17145cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        /**
17155cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * Called when a nested scroll has been accepted by the CoordinatorLayout.
17165cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         *
17175cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * <p>Any Behavior associated with any direct child of the CoordinatorLayout may elect
17185cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * to accept the nested scroll as part of {@link #onStartNestedScroll}. Each Behavior
17195cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * that returned true will receive subsequent nested scroll events for that nested scroll.
17205cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * </p>
17215cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         *
17225cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is
17235cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         *                          associated with
17245cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @param child the child view of the CoordinatorLayout this Behavior is associated with
17255cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @param directTargetChild the child view of the CoordinatorLayout that either is or
17265cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         *                          contains the target of the nested scroll operation
17275cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @param target the descendant view of the CoordinatorLayout initiating the nested scroll
17285cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @param nestedScrollAxes the axes that this nested scroll applies to. See
17295cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         *                         {@link ViewCompat#SCROLL_AXIS_HORIZONTAL},
17305cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         *                         {@link ViewCompat#SCROLL_AXIS_VERTICAL}
17315cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         *
17325cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @see NestedScrollingParent#onNestedScrollAccepted(View, View, int)
17335cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         */
17345cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        public void onNestedScrollAccepted(CoordinatorLayout coordinatorLayout, V child,
17355cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell                View directTargetChild, View target, int nestedScrollAxes) {
17365cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            // Do nothing
17375cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        }
17385cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell
17395cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        /**
17405cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * Called when a nested scroll has ended.
17415cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         *
17425cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * <p>Any Behavior associated with any direct child of the CoordinatorLayout may elect
17435cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * to accept the nested scroll as part of {@link #onStartNestedScroll}. Each Behavior
17445cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * that returned true will receive subsequent nested scroll events for that nested scroll.
17455cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * </p>
17465cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         *
17475cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * <p><code>onStopNestedScroll</code> marks the end of a single nested scroll event
17485cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * sequence. This is a good place to clean up any state related to the nested scroll.
17495cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * </p>
17505cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         *
17515cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is
17525cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         *                          associated with
17535cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @param child the child view of the CoordinatorLayout this Behavior is associated with
17545cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @param target the descendant view of the CoordinatorLayout that initiated
17555cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         *               the nested scroll
17565cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         *
17575cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @see NestedScrollingParent#onStopNestedScroll(View)
17585cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         */
17595cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, V child, View target) {
17605cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            // Do nothing
17615cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        }
17625cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell
17635cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        /**
17645cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * Called when a nested scroll in progress has updated and the target has scrolled or
17655cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * attempted to scroll.
17665cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         *
17675cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * <p>Any Behavior associated with the direct child of the CoordinatorLayout may elect
17685cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * to accept the nested scroll as part of {@link #onStartNestedScroll}. Each Behavior
17695cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * that returned true will receive subsequent nested scroll events for that nested scroll.
17705cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * </p>
17715cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         *
17725cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * <p><code>onNestedScroll</code> is called each time the nested scroll is updated by the
17735cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * nested scrolling child, with both consumed and unconsumed components of the scroll
17745cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * supplied in pixels. <em>Each Behavior responding to the nested scroll will receive the
17755cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * same values.</em>
17765cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * </p>
17775cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         *
17785cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is
17795cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         *                          associated with
17805cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @param child the child view of the CoordinatorLayout this Behavior is associated with
17815cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @param target the descendant view of the CoordinatorLayout performing the nested scroll
17825cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @param dxConsumed horizontal pixels consumed by the target's own scrolling operation
17835cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @param dyConsumed vertical pixels consumed by the target's own scrolling operation
17845cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @param dxUnconsumed horizontal pixels not consumed by the target's own scrolling
17855cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         *                     operation, but requested by the user
17865cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @param dyUnconsumed vertical pixels not consumed by the target's own scrolling operation,
17875cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         *                     but requested by the user
17885cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         *
17895cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @see NestedScrollingParent#onNestedScroll(View, int, int, int, int)
17905cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         */
17915cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        public void onNestedScroll(CoordinatorLayout coordinatorLayout, V child, View target,
17925cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell                int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
17935cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            // Do nothing
17945cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        }
17955cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell
17965cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        /**
17975cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * Called when a nested scroll in progress is about to update, before the target has
17985cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * consumed any of the scrolled distance.
17995cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         *
18005cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * <p>Any Behavior associated with the direct child of the CoordinatorLayout may elect
18015cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * to accept the nested scroll as part of {@link #onStartNestedScroll}. Each Behavior
18025cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * that returned true will receive subsequent nested scroll events for that nested scroll.
18035cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * </p>
18045cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         *
18055cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * <p><code>onNestedPreScroll</code> is called each time the nested scroll is updated
18065cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * by the nested scrolling child, before the nested scrolling child has consumed the scroll
18075cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * distance itself. <em>Each Behavior responding to the nested scroll will receive the
18085cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * same values.</em> The CoordinatorLayout will report as consumed the maximum number
18095cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * of pixels in either direction that any Behavior responding to the nested scroll reported
18105cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * as consumed.</p>
18115cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         *
18125cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is
18135cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         *                          associated with
18145cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @param child the child view of the CoordinatorLayout this Behavior is associated with
18155cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @param target the descendant view of the CoordinatorLayout performing the nested scroll
18165cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @param dx the raw horizontal number of pixels that the user attempted to scroll
18175cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @param dy the raw vertical number of pixels that the user attempted to scroll
18185cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @param consumed out parameter. consumed[0] should be set to the distance of dx that
18195cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         *                 was consumed, consumed[1] should be set to the distance of dy that
18205cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         *                 was consumed
18215cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         *
18225cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @see NestedScrollingParent#onNestedPreScroll(View, int, int, int[])
18235cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         */
18245cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, V child, View target,
18255cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell                int dx, int dy, int[] consumed) {
18265cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            // Do nothing
18275cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        }
18285cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell
18295cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        /**
18305cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * Called when a nested scrolling child is starting a fling or an action that would
18315cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * be a fling.
18325cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         *
18335cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * <p>Any Behavior associated with the direct child of the CoordinatorLayout may elect
18345cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * to accept the nested scroll as part of {@link #onStartNestedScroll}. Each Behavior
18355cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * that returned true will receive subsequent nested scroll events for that nested scroll.
18365cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * </p>
18375cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         *
18385cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * <p><code>onNestedFling</code> is called when the current nested scrolling child view
18395cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * detects the proper conditions for a fling. It reports if the child itself consumed
18405cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * the fling. If it did not, the child is expected to show some sort of overscroll
18415cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * indication. This method should return true if it consumes the fling, so that a child
18425cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * that did not itself take an action in response can choose not to show an overfling
18435cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * indication.</p>
18445cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         *
18455cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is
18465cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         *                          associated with
18475cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @param child the child view of the CoordinatorLayout this Behavior is associated with
18485cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @param target the descendant view of the CoordinatorLayout performing the nested scroll
18495cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @param velocityX horizontal velocity of the attempted fling
18505cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @param velocityY vertical velocity of the attempted fling
18515cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @param consumed true if the nested child view consumed the fling
18525cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @return true if the Behavior consumed the fling
18535cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         *
18545cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @see NestedScrollingParent#onNestedFling(View, float, float, boolean)
18555cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         */
18565cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        public boolean onNestedFling(CoordinatorLayout coordinatorLayout, V child, View target,
18575cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell                float velocityX, float velocityY, boolean consumed) {
18585cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            return false;
18595cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        }
18605cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell
18615cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        /**
18625cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * Called when a nested scrolling child is about to start a fling.
18635cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         *
18645cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * <p>Any Behavior associated with the direct child of the CoordinatorLayout may elect
18655cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * to accept the nested scroll as part of {@link #onStartNestedScroll}. Each Behavior
18665cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * that returned true will receive subsequent nested scroll events for that nested scroll.
18675cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * </p>
18685cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         *
18695cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * <p><code>onNestedPreFling</code> is called when the current nested scrolling child view
18705cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * detects the proper conditions for a fling, but it has not acted on it yet. A
18715cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * Behavior can return true to indicate that it consumed the fling. If at least one
18725cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * Behavior returns true, the fling should not be acted upon by the child.</p>
18735cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         *
18745cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is
18755cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         *                          associated with
18765cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @param child the child view of the CoordinatorLayout this Behavior is associated with
18775cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @param target the descendant view of the CoordinatorLayout performing the nested scroll
18785cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @param velocityX horizontal velocity of the attempted fling
18795cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @param velocityY vertical velocity of the attempted fling
18805cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @return true if the Behavior consumed the fling
18815cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         *
18825cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         * @see NestedScrollingParent#onNestedPreFling(View, float, float)
18835cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell         */
18845cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        public boolean onNestedPreFling(CoordinatorLayout coordinatorLayout, V child, View target,
18855cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell                float velocityX, float velocityY) {
18865cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            return false;
18875cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        }
1888a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
1889a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1890a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    /**
1891a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     * Parameters describing the desired layout for a child of a {@link CoordinatorLayout}.
1892a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell     */
1893a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    public static class LayoutParams extends ViewGroup.MarginLayoutParams {
1894a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        /**
1895a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * A {@link Behavior} that the child view should obey.
1896a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         */
1897a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        Behavior mBehavior;
1898a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1899a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        boolean mBehaviorResolved = false;
1900a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1901a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        /**
1902a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * A {@link Gravity} value describing how this child view should lay out.
1903a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * If an {@link #setAnchorId(int) anchor} is also specified, the gravity describes
1904a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * how this child view should be positioned relative to its anchored position.
1905a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         */
1906a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        public int gravity = Gravity.NO_GRAVITY;
1907a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1908a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        /**
1909a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * A {@link Gravity} value describing which edge of a child view's
1910a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * {@link #getAnchorId() anchor} view the child should position itself relative to.
1911a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         */
1912a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        public int anchorGravity = Gravity.NO_GRAVITY;
1913a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1914a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        /**
1915a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * The index of the horizontal keyline specified to the parent CoordinatorLayout that this
1916a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * child should align relative to. If an {@link #setAnchorId(int) anchor} is present the
1917a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * keyline will be ignored.
1918a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         */
1919a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        public int keyline = -1;
1920a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1921a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        /**
1922a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * A {@link View#getId() view id} of a descendant view of the CoordinatorLayout that
1923a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * this child should position relative to.
1924a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         */
1925a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        int mAnchorId = View.NO_ID;
1926a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1927a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        View mAnchorView;
1928a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        View mAnchorDirectChild;
1929a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
19305cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        private boolean mDidBlockInteraction;
19315cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        private boolean mDidAcceptNestedScroll;
1932a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        private boolean mDidChangeAfterNestedScroll;
1933a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1934a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        final Rect mLastChildRect = new Rect();
1935a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1936a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        Object mBehaviorTag;
1937a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1938a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        public LayoutParams(int width, int height) {
1939a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            super(width, height);
1940a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
1941a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1942a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        LayoutParams(Context context, AttributeSet attrs) {
1943a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            super(context, attrs);
1944a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1945a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            final TypedArray a = context.obtainStyledAttributes(attrs,
1946a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                    R.styleable.CoordinatorLayout_LayoutParams);
1947a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1948a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            this.gravity = a.getInteger(
1949a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                    R.styleable.CoordinatorLayout_LayoutParams_android_layout_gravity,
1950a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                    Gravity.NO_GRAVITY);
1951a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            mAnchorId = a.getResourceId(R.styleable.CoordinatorLayout_LayoutParams_layout_anchor,
1952a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                    View.NO_ID);
1953a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            this.anchorGravity = a.getInteger(
1954a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                    R.styleable.CoordinatorLayout_LayoutParams_layout_anchorGravity,
1955a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                    Gravity.NO_GRAVITY);
1956a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1957a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            this.keyline = a.getInteger(R.styleable.CoordinatorLayout_LayoutParams_layout_keyline,
1958a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                    -1);
1959a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1960a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            mBehaviorResolved = a.hasValue(
1961a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                    R.styleable.CoordinatorLayout_LayoutParams_layout_behavior);
1962a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            if (mBehaviorResolved) {
1963a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                mBehavior = parseBehavior(context, attrs, a.getString(
1964a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                        R.styleable.CoordinatorLayout_LayoutParams_layout_behavior));
1965a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            }
1966a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1967a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            a.recycle();
1968a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
1969a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1970a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        public LayoutParams(LayoutParams p) {
1971a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            super(p);
1972a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
1973a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1974a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        public LayoutParams(MarginLayoutParams p) {
1975a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            super(p);
1976a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
1977a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1978a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        public LayoutParams(ViewGroup.LayoutParams p) {
1979a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            super(p);
1980a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
1981a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1982a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        /**
1983a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * Get the id of this view's anchor.
1984a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *
1985a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * <p>The view with this id must be a descendant of the CoordinatorLayout containing
1986a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * the child view this LayoutParams belongs to. It may not be the child view with
1987a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * this LayoutParams or a descendant of it.</p>
1988a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *
1989a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @return A {@link View#getId() view id} or {@link View#NO_ID} if there is no anchor
1990a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         */
1991a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        public int getAnchorId() {
1992a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            return mAnchorId;
1993a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
1994a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
1995a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        /**
1996a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * Get the id of this view's anchor.
1997a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *
1998a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * <p>The view with this id must be a descendant of the CoordinatorLayout containing
1999a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * the child view this LayoutParams belongs to. It may not be the child view with
2000a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * this LayoutParams or a descendant of it.</p>
2001a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *
2002a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param id The {@link View#getId() view id} of the anchor or
2003a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *           {@link View#NO_ID} if there is no anchor
2004a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         */
2005a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        public void setAnchorId(int id) {
2006a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            invalidateAnchor();
2007a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            mAnchorId = id;
2008a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
2009a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
2010a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        /**
2011a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * Get the behavior governing the layout and interaction of the child view within
2012a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * a parent CoordinatorLayout.
2013a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *
2014a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @return The current behavior or null if no behavior is specified
2015a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         */
2016a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        public Behavior getBehavior() {
2017a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            return mBehavior;
2018a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
2019a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
2020a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        /**
2021a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * Set the behavior governing the layout and interaction of the child view within
2022a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * a parent CoordinatorLayout.
2023a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *
2024a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * <p>Setting a new behavior will remove any currently associated
2025a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * {@link Behavior#setTag(android.view.View, Object) Behavior tag}.</p>
2026a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *
2027a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param behavior The behavior to set or null for no special behavior
2028a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         */
2029a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        public void setBehavior(Behavior behavior) {
2030a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            if (mBehavior != behavior) {
2031a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                mBehavior = behavior;
2032a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                mBehaviorTag = null;
2033a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                mBehaviorResolved = true;
2034a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            }
2035a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
2036a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
2037a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        /**
2038a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * Set the last known position rect for this child view
2039a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param r the rect to set
2040a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         */
2041a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        void setLastChildRect(Rect r) {
2042a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            mLastChildRect.set(r);
2043a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
2044a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
2045a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        /**
2046a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * Get the last known position rect for this child view.
2047a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * Note: do not mutate the result of this call.
2048a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         */
2049a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        Rect getLastChildRect() {
2050a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            return mLastChildRect;
2051a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
2052a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
2053a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        /**
2054a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * Returns true if the anchor id changed to another valid view id since the anchor view
2055a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * was resolved.
2056a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         */
2057a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        boolean checkAnchorChanged() {
2058a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            return mAnchorView == null && mAnchorId != View.NO_ID;
2059a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
2060a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
2061a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        /**
2062a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * Returns true if the associated Behavior previously blocked interaction with other views
2063a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * below the associated child since the touch behavior tracking was last
2064a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * {@link #resetTouchBehaviorTracking() reset}.
2065a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *
2066a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @see #isBlockingInteractionBelow(CoordinatorLayout, android.view.View)
2067a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         */
2068a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        boolean didBlockInteraction() {
2069a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            if (mBehavior == null) {
2070a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                mDidBlockInteraction = false;
2071a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            }
2072a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            return mDidBlockInteraction;
2073a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
2074a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
2075a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        /**
2076a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * Check if the associated Behavior wants to block interaction below the given child
2077a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * view. The given child view should be the child this LayoutParams is associated with.
2078a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *
2079a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * <p>Once interaction is blocked, it will remain blocked until touch interaction tracking
2080a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * is {@link #resetTouchBehaviorTracking() reset}.</p>
2081a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *
2082a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param parent the parent CoordinatorLayout
2083a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param child the child view this LayoutParams is associated with
2084a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @return true to block interaction below the given child
2085a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         */
2086a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        boolean isBlockingInteractionBelow(CoordinatorLayout parent, View child) {
2087a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            if (mDidBlockInteraction) {
2088a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                return true;
2089a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            }
2090a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
2091a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            return mDidBlockInteraction |= mBehavior != null
2092a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                    ? mBehavior.blocksInteractionBelow(parent, child)
2093a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                    : false;
2094a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
2095a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
2096a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        /**
2097a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * Reset tracking of Behavior-specific touch interactions. This includes
2098a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * interaction blocking.
2099a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *
2100a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @see #isBlockingInteractionBelow(CoordinatorLayout, android.view.View)
2101a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @see #didBlockInteraction()
2102a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         */
2103a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        void resetTouchBehaviorTracking() {
2104a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            mDidBlockInteraction = false;
2105a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
2106a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
21075cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        void resetNestedScroll() {
21085cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            mDidAcceptNestedScroll = false;
21095cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        }
21105cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell
21115cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        void acceptNestedScroll(boolean accept) {
21125cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            mDidAcceptNestedScroll = accept;
21135cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        }
21145cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell
21155cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        boolean isNestedScrollAccepted() {
21165cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell            return mDidAcceptNestedScroll;
21175cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell        }
21185cb378077ed5c64d35c1972c5fc84ee11ce31d07Adam Powell
2119a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        boolean getChangedAfterNestedScroll() {
2120a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes            return mDidChangeAfterNestedScroll;
2121a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        }
2122a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
2123a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        void setChangedAfterNestedScroll(boolean changed) {
2124a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes            mDidChangeAfterNestedScroll = changed;
2125a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        }
2126a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
2127a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        void resetChangedAfterNestedScroll() {
2128a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes            mDidChangeAfterNestedScroll = false;
2129a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes        }
2130a6a508b2296730ca6954aaebcca52a9962a5cb55Chris Banes
2131a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        /**
2132a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * Check if an associated child view depends on another child view of the CoordinatorLayout.
2133a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *
2134a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param parent the parent CoordinatorLayout
2135a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param child the child to check
2136a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param dependency the proposed dependency to check
2137a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @return true if child depends on dependency
2138a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         */
2139a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        boolean dependsOn(CoordinatorLayout parent, View child, View dependency) {
2140a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            return dependency == mAnchorDirectChild
2141a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                    || (mBehavior != null && mBehavior.layoutDependsOn(parent, child, dependency));
2142a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
2143a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
2144a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        /**
2145a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * Invalidate the cached anchor view and direct child ancestor of that anchor.
2146a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * The anchor will need to be
2147a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * {@link #findAnchorView(CoordinatorLayout, android.view.View) found} before
2148a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * being used again.
2149a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         */
2150a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        void invalidateAnchor() {
2151a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            mAnchorView = mAnchorDirectChild = null;
2152a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
2153a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
2154a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        /**
2155a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * Locate the appropriate anchor view by the current {@link #setAnchorId(int) anchor id}
2156a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * or return the cached anchor view if already known.
2157a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *
2158a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param parent the parent CoordinatorLayout
2159a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param forChild the child this LayoutParams is associated with
2160a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @return the located descendant anchor view, or null if the anchor id is
2161a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *         {@link View#NO_ID}.
2162a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         */
2163a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        View findAnchorView(CoordinatorLayout parent, View forChild) {
2164a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            if (mAnchorId == View.NO_ID) {
2165a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                mAnchorView = mAnchorDirectChild = null;
2166a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                return null;
2167a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            }
2168a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
2169a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            if (mAnchorView == null || !verifyAnchorView(forChild, parent)) {
2170a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                resolveAnchorView(forChild, parent);
2171a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            }
2172a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            return mAnchorView;
2173a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
2174a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
2175a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        /**
2176a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * Check if the child associated with this LayoutParams is currently considered
2177a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * "dirty" and needs to be updated. A Behavior should consider a child dirty
2178a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * whenever a property returned by another Behavior method would have changed,
2179a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * such as dependencies.
2180a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         *
2181a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param parent the parent CoordinatorLayout
2182a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @param child the child view associated with this LayoutParams
2183a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * @return true if this child view should be considered dirty
2184a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         */
2185a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        boolean isDirty(CoordinatorLayout parent, View child) {
2186a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            return mBehavior != null && mBehavior.isDirty(parent, child);
2187a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
2188a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
2189a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        /**
2190a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * Determine the anchor view for the child view this LayoutParams is assigned to.
2191a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * Assumes mAnchorId is valid.
2192a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         */
2193a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        private void resolveAnchorView(View forChild, CoordinatorLayout parent) {
2194a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            mAnchorView = parent.findViewById(mAnchorId);
2195a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            if (mAnchorView != null) {
2196a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                View directChild = mAnchorView;
2197a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                for (ViewParent p = mAnchorView.getParent();
2198a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                        p != parent && p != null;
2199a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                        p = p.getParent()) {
2200a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                    if (p == forChild) {
2201a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                        if (parent.isInEditMode()) {
2202a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                            mAnchorView = mAnchorDirectChild = null;
2203a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                            return;
2204a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                        }
2205a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                        throw new IllegalStateException(
2206a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                                "Anchor must not be a descendant of the anchored view");
2207a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                    }
2208a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                    if (p instanceof View) {
2209a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                        directChild = (View) p;
2210a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                    }
2211a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                }
2212a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                mAnchorDirectChild = directChild;
2213a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            } else {
2214a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                if (parent.isInEditMode()) {
2215a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                    mAnchorView = mAnchorDirectChild = null;
2216a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                    return;
2217a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                }
2218a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                throw new IllegalStateException("Could not find CoordinatorLayout descendant view"
2219a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                        + " with id " + parent.getResources().getResourceName(mAnchorId)
2220a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                        + " to anchor view " + forChild);
2221a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            }
2222a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
2223a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
2224a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        /**
2225a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * Verify that the previously resolved anchor view is still valid - that it is still
2226a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * a descendant of the expected parent view, it is not the child this LayoutParams
2227a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         * is assigned to or a descendant of it, and it has the expected id.
2228a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell         */
2229a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        private boolean verifyAnchorView(View forChild, CoordinatorLayout parent) {
2230a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            if (mAnchorView.getId() != mAnchorId) {
2231a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                return false;
2232a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            }
2233a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell
2234a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            View directChild = mAnchorView;
2235a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            for (ViewParent p = mAnchorView.getParent();
2236a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                    p != parent;
2237a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                    p = p.getParent()) {
2238a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                if (p == null || p == forChild) {
2239a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                    mAnchorView = mAnchorDirectChild = null;
2240a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                    return false;
2241a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                }
2242a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                if (p instanceof View) {
2243a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                    directChild = (View) p;
2244a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell                }
2245a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            }
2246a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            mAnchorDirectChild = directChild;
2247a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell            return true;
2248a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell        }
2249a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell    }
2250a966c6cda6a3aa562fcfdb842b6c6b35bdd6a3dcAdam Powell}
2251