NestedScrollingChildHelper.java revision ac5fe7c617c66850fff75a9fce9979c6e5674b0f
11fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell/*
2ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * Copyright 2018 The Android Open Source Project
31fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell *
41fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * Licensed under the Apache License, Version 2.0 (the "License");
51fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * you may not use this file except in compliance with the License.
61fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * You may obtain a copy of the License at
71fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell *
81fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell *      http://www.apache.org/licenses/LICENSE-2.0
91fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell *
101fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * Unless required by applicable law or agreed to in writing, software
111fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * distributed under the License is distributed on an "AS IS" BASIS,
121fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * See the License for the specific language governing permissions and
141fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * limitations under the License.
151fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell */
161fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell
171fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell
18ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikaspackage androidx.core.view;
191fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell
20ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static androidx.core.view.ViewCompat.TYPE_NON_TOUCH;
21ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static androidx.core.view.ViewCompat.TYPE_TOUCH;
2276daed103193a1756535d1f59b165e98e1d17445Chris Banes
23ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.annotation.NonNull;
24ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.annotation.Nullable;
25ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.core.view.ViewCompat.NestedScrollType;
26ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.core.view.ViewCompat.ScrollAxis;
271fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powellimport android.view.View;
281fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powellimport android.view.ViewParent;
291fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell
301fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell/**
311fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * Helper class for implementing nested scrolling child views compatible with Android platform
321fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * versions earlier than Android 5.0 Lollipop (API 21).
331fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell *
341fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * <p>{@link android.view.View View} subclasses should instantiate a final instance of this
351fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * class as a field at construction. For each <code>View</code> method that has a matching
36c9a859537b0871f84afeeb706a5b425fe3f2b4ddAurimas Liutikas * method signature in this class, delegate the operation to the helper instance in an overridden
371fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * method implementation. This implements the standard framework policy for nested scrolling.</p>
381fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell *
391fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * <p>Views invoking nested scrolling functionality should always do so from the relevant
40ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * {@link androidx.core.view.ViewCompat}, {@link androidx.core.view.ViewGroupCompat} or
41ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * {@link androidx.core.view.ViewParentCompat} compatibility
421fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * shim static methods. This ensures interoperability with nested scrolling views on Android
431fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * 5.0 Lollipop and newer.</p>
441fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell */
451fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powellpublic class NestedScrollingChildHelper {
4676daed103193a1756535d1f59b165e98e1d17445Chris Banes    private ViewParent mNestedScrollingParentTouch;
4776daed103193a1756535d1f59b165e98e1d17445Chris Banes    private ViewParent mNestedScrollingParentNonTouch;
481fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell    private final View mView;
491fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell    private boolean mIsNestedScrollingEnabled;
501fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell    private int[] mTempNestedScrollConsumed;
511fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell
521fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell    /**
531fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     * Construct a new helper for a given view.
541fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     */
5576daed103193a1756535d1f59b165e98e1d17445Chris Banes    public NestedScrollingChildHelper(@NonNull View view) {
561fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell        mView = view;
571fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell    }
581fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell
591fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell    /**
601fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     * Enable nested scrolling.
611fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     *
621fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass
63ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas     * method/{@link androidx.core.view.NestedScrollingChild} interface method with the same
643ac77bf186f87ecad4bf0063b2f6c4384efbd56aKirill Grouchnikov     * signature to implement the standard policy.</p>
651fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     *
661fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     * @param enabled true to enable nested scrolling dispatch from this view, false otherwise
671fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     */
681fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell    public void setNestedScrollingEnabled(boolean enabled) {
691fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell        if (mIsNestedScrollingEnabled) {
701fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell            ViewCompat.stopNestedScroll(mView);
711fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell        }
721fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell        mIsNestedScrollingEnabled = enabled;
731fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell    }
741fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell
751fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell    /**
761fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     * Check if nested scrolling is enabled for this view.
771fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     *
781fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass
79ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas     * method/{@link androidx.core.view.NestedScrollingChild} interface method with the same
803ac77bf186f87ecad4bf0063b2f6c4384efbd56aKirill Grouchnikov     * signature to implement the standard policy.</p>
811fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     *
821fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     * @return true if nested scrolling is enabled for this view
831fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     */
841fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell    public boolean isNestedScrollingEnabled() {
851fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell        return mIsNestedScrollingEnabled;
861fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell    }
871fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell
881fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell    /**
891fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     * Check if this view has a nested scrolling parent view currently receiving events for
9076daed103193a1756535d1f59b165e98e1d17445Chris Banes     * a nested scroll in progress with the type of touch.
911fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     *
921fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass
93ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas     * method/{@link androidx.core.view.NestedScrollingChild} interface method with the same
943ac77bf186f87ecad4bf0063b2f6c4384efbd56aKirill Grouchnikov     * signature to implement the standard policy.</p>
951fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     *
961fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     * @return true if this view has a nested scrolling parent, false otherwise
971fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     */
981fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell    public boolean hasNestedScrollingParent() {
9976daed103193a1756535d1f59b165e98e1d17445Chris Banes        return hasNestedScrollingParent(TYPE_TOUCH);
10076daed103193a1756535d1f59b165e98e1d17445Chris Banes    }
10176daed103193a1756535d1f59b165e98e1d17445Chris Banes
10276daed103193a1756535d1f59b165e98e1d17445Chris Banes    /**
10376daed103193a1756535d1f59b165e98e1d17445Chris Banes     * Check if this view has a nested scrolling parent view currently receiving events for
10476daed103193a1756535d1f59b165e98e1d17445Chris Banes     * a nested scroll in progress with the given type.
10576daed103193a1756535d1f59b165e98e1d17445Chris Banes     *
10676daed103193a1756535d1f59b165e98e1d17445Chris Banes     * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass
107ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas     * method/{@link androidx.core.view.NestedScrollingChild} interface method with the same
10876daed103193a1756535d1f59b165e98e1d17445Chris Banes     * signature to implement the standard policy.</p>
10976daed103193a1756535d1f59b165e98e1d17445Chris Banes     *
11076daed103193a1756535d1f59b165e98e1d17445Chris Banes     * @return true if this view has a nested scrolling parent, false otherwise
11176daed103193a1756535d1f59b165e98e1d17445Chris Banes     */
11276daed103193a1756535d1f59b165e98e1d17445Chris Banes    public boolean hasNestedScrollingParent(@NestedScrollType int type) {
11376daed103193a1756535d1f59b165e98e1d17445Chris Banes        return getNestedScrollingParentForType(type) != null;
1141fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell    }
1151fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell
1161fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell    /**
1171fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     * Start a new nested scroll for this view.
1181fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     *
1191fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass
120ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas     * method/{@link androidx.core.view.NestedScrollingChild} interface method with the same
1213ac77bf186f87ecad4bf0063b2f6c4384efbd56aKirill Grouchnikov     * signature to implement the standard policy.</p>
1221fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     *
1231fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     * @param axes Supported nested scroll axes.
124ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas     *             See {@link androidx.core.view.NestedScrollingChild#startNestedScroll(int)}.
1251fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     * @return true if a cooperating parent view was found and nested scrolling started successfully
1261fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     */
12776daed103193a1756535d1f59b165e98e1d17445Chris Banes    public boolean startNestedScroll(@ScrollAxis int axes) {
12876daed103193a1756535d1f59b165e98e1d17445Chris Banes        return startNestedScroll(axes, TYPE_TOUCH);
12976daed103193a1756535d1f59b165e98e1d17445Chris Banes    }
13076daed103193a1756535d1f59b165e98e1d17445Chris Banes
13176daed103193a1756535d1f59b165e98e1d17445Chris Banes    /**
13276daed103193a1756535d1f59b165e98e1d17445Chris Banes     * Start a new nested scroll for this view.
13376daed103193a1756535d1f59b165e98e1d17445Chris Banes     *
13476daed103193a1756535d1f59b165e98e1d17445Chris Banes     * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass
135ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas     * method/{@link androidx.core.view.NestedScrollingChild2} interface method with the same
13676daed103193a1756535d1f59b165e98e1d17445Chris Banes     * signature to implement the standard policy.</p>
13776daed103193a1756535d1f59b165e98e1d17445Chris Banes     *
13876daed103193a1756535d1f59b165e98e1d17445Chris Banes     * @param axes Supported nested scroll axes.
139ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas     *             See {@link androidx.core.view.NestedScrollingChild2#startNestedScroll(int,
14076daed103193a1756535d1f59b165e98e1d17445Chris Banes     *             int)}.
14176daed103193a1756535d1f59b165e98e1d17445Chris Banes     * @return true if a cooperating parent view was found and nested scrolling started successfully
14276daed103193a1756535d1f59b165e98e1d17445Chris Banes     */
14376daed103193a1756535d1f59b165e98e1d17445Chris Banes    public boolean startNestedScroll(@ScrollAxis int axes, @NestedScrollType int type) {
14476daed103193a1756535d1f59b165e98e1d17445Chris Banes        if (hasNestedScrollingParent(type)) {
1451fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell            // Already in progress
1461fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell            return true;
1471fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell        }
1481fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell        if (isNestedScrollingEnabled()) {
1491fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell            ViewParent p = mView.getParent();
1501fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell            View child = mView;
1511fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell            while (p != null) {
15276daed103193a1756535d1f59b165e98e1d17445Chris Banes                if (ViewParentCompat.onStartNestedScroll(p, child, mView, axes, type)) {
15376daed103193a1756535d1f59b165e98e1d17445Chris Banes                    setNestedScrollingParentForType(type, p);
15476daed103193a1756535d1f59b165e98e1d17445Chris Banes                    ViewParentCompat.onNestedScrollAccepted(p, child, mView, axes, type);
1551fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell                    return true;
1561fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell                }
1571fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell                if (p instanceof View) {
1581fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell                    child = (View) p;
1591fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell                }
1601fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell                p = p.getParent();
1611fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell            }
1621fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell        }
1631fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell        return false;
1641fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell    }
1651fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell
1661fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell    /**
1671fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     * Stop a nested scroll in progress.
1681fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     *
1691fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass
170ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas     * method/{@link androidx.core.view.NestedScrollingChild} interface method with the same
1713ac77bf186f87ecad4bf0063b2f6c4384efbd56aKirill Grouchnikov     * signature to implement the standard policy.</p>
1721fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     */
1731fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell    public void stopNestedScroll() {
17476daed103193a1756535d1f59b165e98e1d17445Chris Banes        stopNestedScroll(TYPE_TOUCH);
17576daed103193a1756535d1f59b165e98e1d17445Chris Banes    }
17676daed103193a1756535d1f59b165e98e1d17445Chris Banes
17776daed103193a1756535d1f59b165e98e1d17445Chris Banes    /**
17876daed103193a1756535d1f59b165e98e1d17445Chris Banes     * Stop a nested scroll in progress.
17976daed103193a1756535d1f59b165e98e1d17445Chris Banes     *
18076daed103193a1756535d1f59b165e98e1d17445Chris Banes     * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass
181ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas     * method/{@link androidx.core.view.NestedScrollingChild2} interface method with the same
18276daed103193a1756535d1f59b165e98e1d17445Chris Banes     * signature to implement the standard policy.</p>
18376daed103193a1756535d1f59b165e98e1d17445Chris Banes     */
18476daed103193a1756535d1f59b165e98e1d17445Chris Banes    public void stopNestedScroll(@NestedScrollType int type) {
18576daed103193a1756535d1f59b165e98e1d17445Chris Banes        ViewParent parent = getNestedScrollingParentForType(type);
18676daed103193a1756535d1f59b165e98e1d17445Chris Banes        if (parent != null) {
18776daed103193a1756535d1f59b165e98e1d17445Chris Banes            ViewParentCompat.onStopNestedScroll(parent, mView, type);
18876daed103193a1756535d1f59b165e98e1d17445Chris Banes            setNestedScrollingParentForType(type, null);
1891fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell        }
1901fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell    }
1911fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell
1921fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell    /**
1931fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     * Dispatch one step of a nested scrolling operation to the current nested scrolling parent.
1941fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     *
1951fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass
196ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas     * method/{@link androidx.core.view.NestedScrollingChild} interface method with the same
1973ac77bf186f87ecad4bf0063b2f6c4384efbd56aKirill Grouchnikov     * signature to implement the standard policy.</p>
1981fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     *
1991fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     * @return true if the parent consumed any of the nested scroll
2001fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     */
2011fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
20276daed103193a1756535d1f59b165e98e1d17445Chris Banes            int dxUnconsumed, int dyUnconsumed, @Nullable int[] offsetInWindow) {
20376daed103193a1756535d1f59b165e98e1d17445Chris Banes        return dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed,
20476daed103193a1756535d1f59b165e98e1d17445Chris Banes                offsetInWindow, TYPE_TOUCH);
20576daed103193a1756535d1f59b165e98e1d17445Chris Banes    }
20676daed103193a1756535d1f59b165e98e1d17445Chris Banes
20776daed103193a1756535d1f59b165e98e1d17445Chris Banes    /**
20876daed103193a1756535d1f59b165e98e1d17445Chris Banes     * Dispatch one step of a nested scrolling operation to the current nested scrolling parent.
20976daed103193a1756535d1f59b165e98e1d17445Chris Banes     *
21076daed103193a1756535d1f59b165e98e1d17445Chris Banes     * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass
211ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas     * method/{@link androidx.core.view.NestedScrollingChild2} interface method with the same
21276daed103193a1756535d1f59b165e98e1d17445Chris Banes     * signature to implement the standard policy.</p>
21376daed103193a1756535d1f59b165e98e1d17445Chris Banes     *
21476daed103193a1756535d1f59b165e98e1d17445Chris Banes     * @return true if the parent consumed any of the nested scroll
21576daed103193a1756535d1f59b165e98e1d17445Chris Banes     */
21676daed103193a1756535d1f59b165e98e1d17445Chris Banes    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
21776daed103193a1756535d1f59b165e98e1d17445Chris Banes            int dxUnconsumed, int dyUnconsumed, @Nullable int[] offsetInWindow,
21876daed103193a1756535d1f59b165e98e1d17445Chris Banes            @NestedScrollType int type) {
21976daed103193a1756535d1f59b165e98e1d17445Chris Banes        if (isNestedScrollingEnabled()) {
22076daed103193a1756535d1f59b165e98e1d17445Chris Banes            final ViewParent parent = getNestedScrollingParentForType(type);
22176daed103193a1756535d1f59b165e98e1d17445Chris Banes            if (parent == null) {
22276daed103193a1756535d1f59b165e98e1d17445Chris Banes                return false;
22376daed103193a1756535d1f59b165e98e1d17445Chris Banes            }
22476daed103193a1756535d1f59b165e98e1d17445Chris Banes
2251fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell            if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
2261fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell                int startX = 0;
2271fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell                int startY = 0;
2281fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell                if (offsetInWindow != null) {
2291fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell                    mView.getLocationInWindow(offsetInWindow);
2301fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell                    startX = offsetInWindow[0];
2311fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell                    startY = offsetInWindow[1];
2321fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell                }
2331fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell
23476daed103193a1756535d1f59b165e98e1d17445Chris Banes                ViewParentCompat.onNestedScroll(parent, mView, dxConsumed,
23576daed103193a1756535d1f59b165e98e1d17445Chris Banes                        dyConsumed, dxUnconsumed, dyUnconsumed, type);
2361fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell
2371fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell                if (offsetInWindow != null) {
2381fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell                    mView.getLocationInWindow(offsetInWindow);
2391fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell                    offsetInWindow[0] -= startX;
2401fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell                    offsetInWindow[1] -= startY;
2411fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell                }
2421fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell                return true;
2431fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell            } else if (offsetInWindow != null) {
2441fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell                // No motion, no dispatch. Keep offsetInWindow up to date.
2451fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell                offsetInWindow[0] = 0;
2461fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell                offsetInWindow[1] = 0;
2471fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell            }
2481fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell        }
2491fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell        return false;
2501fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell    }
2511fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell
2521fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell    /**
2531fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     * Dispatch one step of a nested pre-scrolling operation to the current nested scrolling parent.
2541fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     *
2551fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass
256ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas     * method/{@link androidx.core.view.NestedScrollingChild} interface method with the same
2573ac77bf186f87ecad4bf0063b2f6c4384efbd56aKirill Grouchnikov     * signature to implement the standard policy.</p>
2581fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     *
2591fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     * @return true if the parent consumed any of the nested scroll
2601fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     */
26176daed103193a1756535d1f59b165e98e1d17445Chris Banes    public boolean dispatchNestedPreScroll(int dx, int dy, @Nullable int[] consumed,
26276daed103193a1756535d1f59b165e98e1d17445Chris Banes            @Nullable int[] offsetInWindow) {
26376daed103193a1756535d1f59b165e98e1d17445Chris Banes        return dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow, TYPE_TOUCH);
26476daed103193a1756535d1f59b165e98e1d17445Chris Banes    }
26576daed103193a1756535d1f59b165e98e1d17445Chris Banes
26676daed103193a1756535d1f59b165e98e1d17445Chris Banes    /**
26776daed103193a1756535d1f59b165e98e1d17445Chris Banes     * Dispatch one step of a nested pre-scrolling operation to the current nested scrolling parent.
26876daed103193a1756535d1f59b165e98e1d17445Chris Banes     *
26976daed103193a1756535d1f59b165e98e1d17445Chris Banes     * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass
270ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas     * method/{@link androidx.core.view.NestedScrollingChild2} interface method with the same
27176daed103193a1756535d1f59b165e98e1d17445Chris Banes     * signature to implement the standard policy.</p>
27276daed103193a1756535d1f59b165e98e1d17445Chris Banes     *
27376daed103193a1756535d1f59b165e98e1d17445Chris Banes     * @return true if the parent consumed any of the nested scroll
27476daed103193a1756535d1f59b165e98e1d17445Chris Banes     */
27576daed103193a1756535d1f59b165e98e1d17445Chris Banes    public boolean dispatchNestedPreScroll(int dx, int dy, @Nullable int[] consumed,
27676daed103193a1756535d1f59b165e98e1d17445Chris Banes            @Nullable int[] offsetInWindow, @NestedScrollType int type) {
27776daed103193a1756535d1f59b165e98e1d17445Chris Banes        if (isNestedScrollingEnabled()) {
27876daed103193a1756535d1f59b165e98e1d17445Chris Banes            final ViewParent parent = getNestedScrollingParentForType(type);
27976daed103193a1756535d1f59b165e98e1d17445Chris Banes            if (parent == null) {
28076daed103193a1756535d1f59b165e98e1d17445Chris Banes                return false;
28176daed103193a1756535d1f59b165e98e1d17445Chris Banes            }
28276daed103193a1756535d1f59b165e98e1d17445Chris Banes
2831fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell            if (dx != 0 || dy != 0) {
2841fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell                int startX = 0;
2851fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell                int startY = 0;
2861fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell                if (offsetInWindow != null) {
2871fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell                    mView.getLocationInWindow(offsetInWindow);
2881fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell                    startX = offsetInWindow[0];
2891fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell                    startY = offsetInWindow[1];
2901fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell                }
2911fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell
2921fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell                if (consumed == null) {
2931fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell                    if (mTempNestedScrollConsumed == null) {
2941fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell                        mTempNestedScrollConsumed = new int[2];
2951fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell                    }
2961fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell                    consumed = mTempNestedScrollConsumed;
2971fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell                }
2981fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell                consumed[0] = 0;
2991fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell                consumed[1] = 0;
30076daed103193a1756535d1f59b165e98e1d17445Chris Banes                ViewParentCompat.onNestedPreScroll(parent, mView, dx, dy, consumed, type);
3011fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell
3021fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell                if (offsetInWindow != null) {
3031fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell                    mView.getLocationInWindow(offsetInWindow);
3041fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell                    offsetInWindow[0] -= startX;
3051fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell                    offsetInWindow[1] -= startY;
3061fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell                }
3071fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell                return consumed[0] != 0 || consumed[1] != 0;
3081fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell            } else if (offsetInWindow != null) {
3091fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell                offsetInWindow[0] = 0;
3101fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell                offsetInWindow[1] = 0;
3111fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell            }
3121fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell        }
3131fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell        return false;
3141fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell    }
3151fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell
3161fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell    /**
3171fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     * Dispatch a nested fling operation to the current nested scrolling parent.
3181fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     *
3191fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass
320ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas     * method/{@link androidx.core.view.NestedScrollingChild} interface method with the same
3213ac77bf186f87ecad4bf0063b2f6c4384efbd56aKirill Grouchnikov     * signature to implement the standard policy.</p>
3221fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     *
3231fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     * @return true if the parent consumed the nested fling
3241fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     */
3251fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell    public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
32676daed103193a1756535d1f59b165e98e1d17445Chris Banes        if (isNestedScrollingEnabled()) {
32776daed103193a1756535d1f59b165e98e1d17445Chris Banes            ViewParent parent = getNestedScrollingParentForType(TYPE_TOUCH);
32876daed103193a1756535d1f59b165e98e1d17445Chris Banes            if (parent != null) {
32976daed103193a1756535d1f59b165e98e1d17445Chris Banes                return ViewParentCompat.onNestedFling(parent, mView, velocityX,
33076daed103193a1756535d1f59b165e98e1d17445Chris Banes                        velocityY, consumed);
33176daed103193a1756535d1f59b165e98e1d17445Chris Banes            }
3321fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell        }
3331fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell        return false;
3341fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell    }
3351fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell
3361fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell    /**
3371fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     * Dispatch a nested pre-fling operation to the current nested scrolling parent.
3381fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     *
3391fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass
340ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas     * method/{@link androidx.core.view.NestedScrollingChild} interface method with the same
3413ac77bf186f87ecad4bf0063b2f6c4384efbd56aKirill Grouchnikov     * signature to implement the standard policy.</p>
3421fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     *
3431fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     * @return true if the parent consumed the nested fling
3441fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     */
3451fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell    public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
34676daed103193a1756535d1f59b165e98e1d17445Chris Banes        if (isNestedScrollingEnabled()) {
34776daed103193a1756535d1f59b165e98e1d17445Chris Banes            ViewParent parent = getNestedScrollingParentForType(TYPE_TOUCH);
34876daed103193a1756535d1f59b165e98e1d17445Chris Banes            if (parent != null) {
34976daed103193a1756535d1f59b165e98e1d17445Chris Banes                return ViewParentCompat.onNestedPreFling(parent, mView, velocityX,
35076daed103193a1756535d1f59b165e98e1d17445Chris Banes                        velocityY);
35176daed103193a1756535d1f59b165e98e1d17445Chris Banes            }
3521fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell        }
3531fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell        return false;
3541fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell    }
3551fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell
3561fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell    /**
3571fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     * View subclasses should always call this method on their
3581fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     * <code>NestedScrollingChildHelper</code> when detached from a window.
3591fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     *
3601fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass
361ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas     * method/{@link androidx.core.view.NestedScrollingChild} interface method with the same
3623ac77bf186f87ecad4bf0063b2f6c4384efbd56aKirill Grouchnikov     * signature to implement the standard policy.</p>
3631fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     */
3641fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell    public void onDetachedFromWindow() {
3651fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell        ViewCompat.stopNestedScroll(mView);
3661fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell    }
3671fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell
3681fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell    /**
3691fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     * Called when a nested scrolling child stops its current nested scroll operation.
3701fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     *
3711fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass
372ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas     * method/{@link androidx.core.view.NestedScrollingChild} interface method with the same
3733ac77bf186f87ecad4bf0063b2f6c4384efbd56aKirill Grouchnikov     * signature to implement the standard policy.</p>
3741fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     *
3751fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     * @param child Child view stopping its nested scroll. This may not be a direct child view.
3761fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell     */
37776daed103193a1756535d1f59b165e98e1d17445Chris Banes    public void onStopNestedScroll(@NonNull View child) {
3781fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell        ViewCompat.stopNestedScroll(mView);
3791fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell    }
38076daed103193a1756535d1f59b165e98e1d17445Chris Banes
38176daed103193a1756535d1f59b165e98e1d17445Chris Banes    private ViewParent getNestedScrollingParentForType(@NestedScrollType int type) {
38276daed103193a1756535d1f59b165e98e1d17445Chris Banes        switch (type) {
38376daed103193a1756535d1f59b165e98e1d17445Chris Banes            case TYPE_TOUCH:
38476daed103193a1756535d1f59b165e98e1d17445Chris Banes                return mNestedScrollingParentTouch;
38576daed103193a1756535d1f59b165e98e1d17445Chris Banes            case TYPE_NON_TOUCH:
38676daed103193a1756535d1f59b165e98e1d17445Chris Banes                return mNestedScrollingParentNonTouch;
38776daed103193a1756535d1f59b165e98e1d17445Chris Banes        }
38876daed103193a1756535d1f59b165e98e1d17445Chris Banes        return null;
38976daed103193a1756535d1f59b165e98e1d17445Chris Banes    }
39076daed103193a1756535d1f59b165e98e1d17445Chris Banes
39176daed103193a1756535d1f59b165e98e1d17445Chris Banes    private void setNestedScrollingParentForType(@NestedScrollType int type, ViewParent p) {
39276daed103193a1756535d1f59b165e98e1d17445Chris Banes        switch (type) {
39376daed103193a1756535d1f59b165e98e1d17445Chris Banes            case TYPE_TOUCH:
39476daed103193a1756535d1f59b165e98e1d17445Chris Banes                mNestedScrollingParentTouch = p;
39576daed103193a1756535d1f59b165e98e1d17445Chris Banes                break;
39676daed103193a1756535d1f59b165e98e1d17445Chris Banes            case TYPE_NON_TOUCH:
39776daed103193a1756535d1f59b165e98e1d17445Chris Banes                mNestedScrollingParentNonTouch = p;
39876daed103193a1756535d1f59b165e98e1d17445Chris Banes                break;
39976daed103193a1756535d1f59b165e98e1d17445Chris Banes        }
40076daed103193a1756535d1f59b165e98e1d17445Chris Banes    }
4011fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell}
402