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 239dede51868bbbe16aadcd65e04860bea8ea50e05Aurimas Liutikasimport android.view.View; 249dede51868bbbe16aadcd65e04860bea8ea50e05Aurimas Liutikasimport android.view.ViewParent; 259dede51868bbbe16aadcd65e04860bea8ea50e05Aurimas Liutikas 26ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.annotation.NonNull; 27ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.annotation.Nullable; 28ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.core.view.ViewCompat.NestedScrollType; 29ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.core.view.ViewCompat.ScrollAxis; 301fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell 311fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell/** 321fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * Helper class for implementing nested scrolling child views compatible with Android platform 331fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * versions earlier than Android 5.0 Lollipop (API 21). 341fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * 351fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * <p>{@link android.view.View View} subclasses should instantiate a final instance of this 361fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * class as a field at construction. For each <code>View</code> method that has a matching 37c9a859537b0871f84afeeb706a5b425fe3f2b4ddAurimas Liutikas * method signature in this class, delegate the operation to the helper instance in an overridden 381fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * method implementation. This implements the standard framework policy for nested scrolling.</p> 391fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * 401fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * <p>Views invoking nested scrolling functionality should always do so from the relevant 41ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * {@link androidx.core.view.ViewCompat}, {@link androidx.core.view.ViewGroupCompat} or 42ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * {@link androidx.core.view.ViewParentCompat} compatibility 431fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * shim static methods. This ensures interoperability with nested scrolling views on Android 441fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * 5.0 Lollipop and newer.</p> 451fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell */ 461fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powellpublic class NestedScrollingChildHelper { 4776daed103193a1756535d1f59b165e98e1d17445Chris Banes private ViewParent mNestedScrollingParentTouch; 4876daed103193a1756535d1f59b165e98e1d17445Chris Banes private ViewParent mNestedScrollingParentNonTouch; 491fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell private final View mView; 501fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell private boolean mIsNestedScrollingEnabled; 511fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell private int[] mTempNestedScrollConsumed; 521fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell 531fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell /** 541fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * Construct a new helper for a given view. 551fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell */ 5676daed103193a1756535d1f59b165e98e1d17445Chris Banes public NestedScrollingChildHelper(@NonNull View view) { 571fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell mView = view; 581fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell } 591fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell 601fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell /** 611fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * Enable nested scrolling. 621fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * 631fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass 64ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * method/{@link androidx.core.view.NestedScrollingChild} interface method with the same 653ac77bf186f87ecad4bf0063b2f6c4384efbd56aKirill Grouchnikov * signature to implement the standard policy.</p> 661fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * 671fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * @param enabled true to enable nested scrolling dispatch from this view, false otherwise 681fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell */ 691fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell public void setNestedScrollingEnabled(boolean enabled) { 701fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell if (mIsNestedScrollingEnabled) { 711fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell ViewCompat.stopNestedScroll(mView); 721fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell } 731fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell mIsNestedScrollingEnabled = enabled; 741fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell } 751fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell 761fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell /** 771fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * Check if nested scrolling is enabled for this view. 781fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * 791fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass 80ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * method/{@link androidx.core.view.NestedScrollingChild} interface method with the same 813ac77bf186f87ecad4bf0063b2f6c4384efbd56aKirill Grouchnikov * signature to implement the standard policy.</p> 821fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * 831fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * @return true if nested scrolling is enabled for this view 841fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell */ 851fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell public boolean isNestedScrollingEnabled() { 861fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell return mIsNestedScrollingEnabled; 871fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell } 881fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell 891fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell /** 901fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * Check if this view has a nested scrolling parent view currently receiving events for 9176daed103193a1756535d1f59b165e98e1d17445Chris Banes * a nested scroll in progress with the type of touch. 921fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * 931fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass 94ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * method/{@link androidx.core.view.NestedScrollingChild} interface method with the same 953ac77bf186f87ecad4bf0063b2f6c4384efbd56aKirill Grouchnikov * signature to implement the standard policy.</p> 961fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * 971fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * @return true if this view has a nested scrolling parent, false otherwise 981fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell */ 991fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell public boolean hasNestedScrollingParent() { 10076daed103193a1756535d1f59b165e98e1d17445Chris Banes return hasNestedScrollingParent(TYPE_TOUCH); 10176daed103193a1756535d1f59b165e98e1d17445Chris Banes } 10276daed103193a1756535d1f59b165e98e1d17445Chris Banes 10376daed103193a1756535d1f59b165e98e1d17445Chris Banes /** 10476daed103193a1756535d1f59b165e98e1d17445Chris Banes * Check if this view has a nested scrolling parent view currently receiving events for 10576daed103193a1756535d1f59b165e98e1d17445Chris Banes * a nested scroll in progress with the given type. 10676daed103193a1756535d1f59b165e98e1d17445Chris Banes * 10776daed103193a1756535d1f59b165e98e1d17445Chris Banes * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass 108ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * method/{@link androidx.core.view.NestedScrollingChild} interface method with the same 10976daed103193a1756535d1f59b165e98e1d17445Chris Banes * signature to implement the standard policy.</p> 11076daed103193a1756535d1f59b165e98e1d17445Chris Banes * 11176daed103193a1756535d1f59b165e98e1d17445Chris Banes * @return true if this view has a nested scrolling parent, false otherwise 11276daed103193a1756535d1f59b165e98e1d17445Chris Banes */ 11376daed103193a1756535d1f59b165e98e1d17445Chris Banes public boolean hasNestedScrollingParent(@NestedScrollType int type) { 11476daed103193a1756535d1f59b165e98e1d17445Chris Banes return getNestedScrollingParentForType(type) != null; 1151fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell } 1161fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell 1171fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell /** 1181fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * Start a new nested scroll for this view. 1191fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * 1201fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass 121ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * method/{@link androidx.core.view.NestedScrollingChild} interface method with the same 1223ac77bf186f87ecad4bf0063b2f6c4384efbd56aKirill Grouchnikov * signature to implement the standard policy.</p> 1231fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * 1241fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * @param axes Supported nested scroll axes. 125ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * See {@link androidx.core.view.NestedScrollingChild#startNestedScroll(int)}. 1261fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * @return true if a cooperating parent view was found and nested scrolling started successfully 1271fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell */ 12876daed103193a1756535d1f59b165e98e1d17445Chris Banes public boolean startNestedScroll(@ScrollAxis int axes) { 12976daed103193a1756535d1f59b165e98e1d17445Chris Banes return startNestedScroll(axes, TYPE_TOUCH); 13076daed103193a1756535d1f59b165e98e1d17445Chris Banes } 13176daed103193a1756535d1f59b165e98e1d17445Chris Banes 13276daed103193a1756535d1f59b165e98e1d17445Chris Banes /** 13376daed103193a1756535d1f59b165e98e1d17445Chris Banes * Start a new nested scroll for this view. 13476daed103193a1756535d1f59b165e98e1d17445Chris Banes * 13576daed103193a1756535d1f59b165e98e1d17445Chris Banes * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass 136ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * method/{@link androidx.core.view.NestedScrollingChild2} interface method with the same 13776daed103193a1756535d1f59b165e98e1d17445Chris Banes * signature to implement the standard policy.</p> 13876daed103193a1756535d1f59b165e98e1d17445Chris Banes * 13976daed103193a1756535d1f59b165e98e1d17445Chris Banes * @param axes Supported nested scroll axes. 140ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * See {@link androidx.core.view.NestedScrollingChild2#startNestedScroll(int, 14176daed103193a1756535d1f59b165e98e1d17445Chris Banes * int)}. 14276daed103193a1756535d1f59b165e98e1d17445Chris Banes * @return true if a cooperating parent view was found and nested scrolling started successfully 14376daed103193a1756535d1f59b165e98e1d17445Chris Banes */ 14476daed103193a1756535d1f59b165e98e1d17445Chris Banes public boolean startNestedScroll(@ScrollAxis int axes, @NestedScrollType int type) { 14576daed103193a1756535d1f59b165e98e1d17445Chris Banes if (hasNestedScrollingParent(type)) { 1461fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell // Already in progress 1471fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell return true; 1481fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell } 1491fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell if (isNestedScrollingEnabled()) { 1501fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell ViewParent p = mView.getParent(); 1511fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell View child = mView; 1521fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell while (p != null) { 15376daed103193a1756535d1f59b165e98e1d17445Chris Banes if (ViewParentCompat.onStartNestedScroll(p, child, mView, axes, type)) { 15476daed103193a1756535d1f59b165e98e1d17445Chris Banes setNestedScrollingParentForType(type, p); 15576daed103193a1756535d1f59b165e98e1d17445Chris Banes ViewParentCompat.onNestedScrollAccepted(p, child, mView, axes, type); 1561fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell return true; 1571fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell } 1581fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell if (p instanceof View) { 1591fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell child = (View) p; 1601fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell } 1611fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell p = p.getParent(); 1621fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell } 1631fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell } 1641fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell return false; 1651fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell } 1661fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell 1671fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell /** 1681fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * Stop a nested scroll in progress. 1691fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * 1701fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass 171ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * method/{@link androidx.core.view.NestedScrollingChild} interface method with the same 1723ac77bf186f87ecad4bf0063b2f6c4384efbd56aKirill Grouchnikov * signature to implement the standard policy.</p> 1731fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell */ 1741fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell public void stopNestedScroll() { 17576daed103193a1756535d1f59b165e98e1d17445Chris Banes stopNestedScroll(TYPE_TOUCH); 17676daed103193a1756535d1f59b165e98e1d17445Chris Banes } 17776daed103193a1756535d1f59b165e98e1d17445Chris Banes 17876daed103193a1756535d1f59b165e98e1d17445Chris Banes /** 17976daed103193a1756535d1f59b165e98e1d17445Chris Banes * Stop a nested scroll in progress. 18076daed103193a1756535d1f59b165e98e1d17445Chris Banes * 18176daed103193a1756535d1f59b165e98e1d17445Chris Banes * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass 182ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * method/{@link androidx.core.view.NestedScrollingChild2} interface method with the same 18376daed103193a1756535d1f59b165e98e1d17445Chris Banes * signature to implement the standard policy.</p> 18476daed103193a1756535d1f59b165e98e1d17445Chris Banes */ 18576daed103193a1756535d1f59b165e98e1d17445Chris Banes public void stopNestedScroll(@NestedScrollType int type) { 18676daed103193a1756535d1f59b165e98e1d17445Chris Banes ViewParent parent = getNestedScrollingParentForType(type); 18776daed103193a1756535d1f59b165e98e1d17445Chris Banes if (parent != null) { 18876daed103193a1756535d1f59b165e98e1d17445Chris Banes ViewParentCompat.onStopNestedScroll(parent, mView, type); 18976daed103193a1756535d1f59b165e98e1d17445Chris Banes setNestedScrollingParentForType(type, null); 1901fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell } 1911fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell } 1921fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell 1931fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell /** 1941fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * Dispatch one step of a nested scrolling operation to the current nested scrolling parent. 1951fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * 1961fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass 197ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * method/{@link androidx.core.view.NestedScrollingChild} interface method with the same 1983ac77bf186f87ecad4bf0063b2f6c4384efbd56aKirill Grouchnikov * signature to implement the standard policy.</p> 1991fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * 2001fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * @return true if the parent consumed any of the nested scroll 2011fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell */ 2021fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, 20376daed103193a1756535d1f59b165e98e1d17445Chris Banes int dxUnconsumed, int dyUnconsumed, @Nullable int[] offsetInWindow) { 20476daed103193a1756535d1f59b165e98e1d17445Chris Banes return dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, 20576daed103193a1756535d1f59b165e98e1d17445Chris Banes offsetInWindow, TYPE_TOUCH); 20676daed103193a1756535d1f59b165e98e1d17445Chris Banes } 20776daed103193a1756535d1f59b165e98e1d17445Chris Banes 20876daed103193a1756535d1f59b165e98e1d17445Chris Banes /** 20976daed103193a1756535d1f59b165e98e1d17445Chris Banes * Dispatch one step of a nested scrolling operation to the current nested scrolling parent. 21076daed103193a1756535d1f59b165e98e1d17445Chris Banes * 21176daed103193a1756535d1f59b165e98e1d17445Chris Banes * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass 212ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * method/{@link androidx.core.view.NestedScrollingChild2} interface method with the same 21376daed103193a1756535d1f59b165e98e1d17445Chris Banes * signature to implement the standard policy.</p> 21476daed103193a1756535d1f59b165e98e1d17445Chris Banes * 21576daed103193a1756535d1f59b165e98e1d17445Chris Banes * @return true if the parent consumed any of the nested scroll 21676daed103193a1756535d1f59b165e98e1d17445Chris Banes */ 21776daed103193a1756535d1f59b165e98e1d17445Chris Banes public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, 21876daed103193a1756535d1f59b165e98e1d17445Chris Banes int dxUnconsumed, int dyUnconsumed, @Nullable int[] offsetInWindow, 21976daed103193a1756535d1f59b165e98e1d17445Chris Banes @NestedScrollType int type) { 22076daed103193a1756535d1f59b165e98e1d17445Chris Banes if (isNestedScrollingEnabled()) { 22176daed103193a1756535d1f59b165e98e1d17445Chris Banes final ViewParent parent = getNestedScrollingParentForType(type); 22276daed103193a1756535d1f59b165e98e1d17445Chris Banes if (parent == null) { 22376daed103193a1756535d1f59b165e98e1d17445Chris Banes return false; 22476daed103193a1756535d1f59b165e98e1d17445Chris Banes } 22576daed103193a1756535d1f59b165e98e1d17445Chris Banes 2261fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) { 2271fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell int startX = 0; 2281fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell int startY = 0; 2291fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell if (offsetInWindow != null) { 2301fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell mView.getLocationInWindow(offsetInWindow); 2311fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell startX = offsetInWindow[0]; 2321fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell startY = offsetInWindow[1]; 2331fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell } 2341fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell 23576daed103193a1756535d1f59b165e98e1d17445Chris Banes ViewParentCompat.onNestedScroll(parent, mView, dxConsumed, 23676daed103193a1756535d1f59b165e98e1d17445Chris Banes dyConsumed, dxUnconsumed, dyUnconsumed, type); 2371fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell 2381fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell if (offsetInWindow != null) { 2391fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell mView.getLocationInWindow(offsetInWindow); 2401fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell offsetInWindow[0] -= startX; 2411fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell offsetInWindow[1] -= startY; 2421fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell } 2431fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell return true; 2441fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell } else if (offsetInWindow != null) { 2451fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell // No motion, no dispatch. Keep offsetInWindow up to date. 2461fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell offsetInWindow[0] = 0; 2471fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell offsetInWindow[1] = 0; 2481fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell } 2491fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell } 2501fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell return false; 2511fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell } 2521fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell 2531fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell /** 2541fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * Dispatch one step of a nested pre-scrolling operation to the current nested scrolling parent. 2551fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * 2561fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass 257ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * method/{@link androidx.core.view.NestedScrollingChild} interface method with the same 2583ac77bf186f87ecad4bf0063b2f6c4384efbd56aKirill Grouchnikov * signature to implement the standard policy.</p> 2591fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * 2601fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * @return true if the parent consumed any of the nested scroll 2611fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell */ 26276daed103193a1756535d1f59b165e98e1d17445Chris Banes public boolean dispatchNestedPreScroll(int dx, int dy, @Nullable int[] consumed, 26376daed103193a1756535d1f59b165e98e1d17445Chris Banes @Nullable int[] offsetInWindow) { 26476daed103193a1756535d1f59b165e98e1d17445Chris Banes return dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow, TYPE_TOUCH); 26576daed103193a1756535d1f59b165e98e1d17445Chris Banes } 26676daed103193a1756535d1f59b165e98e1d17445Chris Banes 26776daed103193a1756535d1f59b165e98e1d17445Chris Banes /** 26876daed103193a1756535d1f59b165e98e1d17445Chris Banes * Dispatch one step of a nested pre-scrolling operation to the current nested scrolling parent. 26976daed103193a1756535d1f59b165e98e1d17445Chris Banes * 27076daed103193a1756535d1f59b165e98e1d17445Chris Banes * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass 271ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * method/{@link androidx.core.view.NestedScrollingChild2} interface method with the same 27276daed103193a1756535d1f59b165e98e1d17445Chris Banes * signature to implement the standard policy.</p> 27376daed103193a1756535d1f59b165e98e1d17445Chris Banes * 27476daed103193a1756535d1f59b165e98e1d17445Chris Banes * @return true if the parent consumed any of the nested scroll 27576daed103193a1756535d1f59b165e98e1d17445Chris Banes */ 27676daed103193a1756535d1f59b165e98e1d17445Chris Banes public boolean dispatchNestedPreScroll(int dx, int dy, @Nullable int[] consumed, 27776daed103193a1756535d1f59b165e98e1d17445Chris Banes @Nullable int[] offsetInWindow, @NestedScrollType int type) { 27876daed103193a1756535d1f59b165e98e1d17445Chris Banes if (isNestedScrollingEnabled()) { 27976daed103193a1756535d1f59b165e98e1d17445Chris Banes final ViewParent parent = getNestedScrollingParentForType(type); 28076daed103193a1756535d1f59b165e98e1d17445Chris Banes if (parent == null) { 28176daed103193a1756535d1f59b165e98e1d17445Chris Banes return false; 28276daed103193a1756535d1f59b165e98e1d17445Chris Banes } 28376daed103193a1756535d1f59b165e98e1d17445Chris Banes 2841fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell if (dx != 0 || dy != 0) { 2851fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell int startX = 0; 2861fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell int startY = 0; 2871fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell if (offsetInWindow != null) { 2881fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell mView.getLocationInWindow(offsetInWindow); 2891fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell startX = offsetInWindow[0]; 2901fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell startY = offsetInWindow[1]; 2911fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell } 2921fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell 2931fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell if (consumed == null) { 2941fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell if (mTempNestedScrollConsumed == null) { 2951fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell mTempNestedScrollConsumed = new int[2]; 2961fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell } 2971fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell consumed = mTempNestedScrollConsumed; 2981fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell } 2991fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell consumed[0] = 0; 3001fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell consumed[1] = 0; 30176daed103193a1756535d1f59b165e98e1d17445Chris Banes ViewParentCompat.onNestedPreScroll(parent, mView, dx, dy, consumed, type); 3021fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell 3031fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell if (offsetInWindow != null) { 3041fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell mView.getLocationInWindow(offsetInWindow); 3051fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell offsetInWindow[0] -= startX; 3061fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell offsetInWindow[1] -= startY; 3071fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell } 3081fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell return consumed[0] != 0 || consumed[1] != 0; 3091fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell } else if (offsetInWindow != null) { 3101fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell offsetInWindow[0] = 0; 3111fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell offsetInWindow[1] = 0; 3121fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell } 3131fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell } 3141fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell return false; 3151fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell } 3161fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell 3171fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell /** 3181fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * Dispatch a nested fling operation to the current nested scrolling parent. 3191fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * 3201fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass 321ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * method/{@link androidx.core.view.NestedScrollingChild} interface method with the same 3223ac77bf186f87ecad4bf0063b2f6c4384efbd56aKirill Grouchnikov * signature to implement the standard policy.</p> 3231fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * 3241fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * @return true if the parent consumed the nested fling 3251fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell */ 3261fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) { 32776daed103193a1756535d1f59b165e98e1d17445Chris Banes if (isNestedScrollingEnabled()) { 32876daed103193a1756535d1f59b165e98e1d17445Chris Banes ViewParent parent = getNestedScrollingParentForType(TYPE_TOUCH); 32976daed103193a1756535d1f59b165e98e1d17445Chris Banes if (parent != null) { 33076daed103193a1756535d1f59b165e98e1d17445Chris Banes return ViewParentCompat.onNestedFling(parent, mView, velocityX, 33176daed103193a1756535d1f59b165e98e1d17445Chris Banes velocityY, consumed); 33276daed103193a1756535d1f59b165e98e1d17445Chris Banes } 3331fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell } 3341fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell return false; 3351fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell } 3361fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell 3371fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell /** 3381fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * Dispatch a nested pre-fling operation to the current nested scrolling parent. 3391fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * 3401fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass 341ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * method/{@link androidx.core.view.NestedScrollingChild} interface method with the same 3423ac77bf186f87ecad4bf0063b2f6c4384efbd56aKirill Grouchnikov * signature to implement the standard policy.</p> 3431fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * 3441fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * @return true if the parent consumed the nested fling 3451fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell */ 3461fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell public boolean dispatchNestedPreFling(float velocityX, float velocityY) { 34776daed103193a1756535d1f59b165e98e1d17445Chris Banes if (isNestedScrollingEnabled()) { 34876daed103193a1756535d1f59b165e98e1d17445Chris Banes ViewParent parent = getNestedScrollingParentForType(TYPE_TOUCH); 34976daed103193a1756535d1f59b165e98e1d17445Chris Banes if (parent != null) { 35076daed103193a1756535d1f59b165e98e1d17445Chris Banes return ViewParentCompat.onNestedPreFling(parent, mView, velocityX, 35176daed103193a1756535d1f59b165e98e1d17445Chris Banes velocityY); 35276daed103193a1756535d1f59b165e98e1d17445Chris Banes } 3531fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell } 3541fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell return false; 3551fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell } 3561fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell 3571fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell /** 3581fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * View subclasses should always call this method on their 3591fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * <code>NestedScrollingChildHelper</code> when detached from a window. 3601fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * 3611fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass 362ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * method/{@link androidx.core.view.NestedScrollingChild} interface method with the same 3633ac77bf186f87ecad4bf0063b2f6c4384efbd56aKirill Grouchnikov * signature to implement the standard policy.</p> 3641fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell */ 3651fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell public void onDetachedFromWindow() { 3661fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell ViewCompat.stopNestedScroll(mView); 3671fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell } 3681fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell 3691fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell /** 3701fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * Called when a nested scrolling child stops its current nested scroll operation. 3711fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * 3721fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass 373ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * method/{@link androidx.core.view.NestedScrollingChild} interface method with the same 3743ac77bf186f87ecad4bf0063b2f6c4384efbd56aKirill Grouchnikov * signature to implement the standard policy.</p> 3751fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * 3761fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell * @param child Child view stopping its nested scroll. This may not be a direct child view. 3771fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell */ 37876daed103193a1756535d1f59b165e98e1d17445Chris Banes public void onStopNestedScroll(@NonNull View child) { 3791fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell ViewCompat.stopNestedScroll(mView); 3801fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell } 38176daed103193a1756535d1f59b165e98e1d17445Chris Banes 38276daed103193a1756535d1f59b165e98e1d17445Chris Banes private ViewParent getNestedScrollingParentForType(@NestedScrollType int type) { 38376daed103193a1756535d1f59b165e98e1d17445Chris Banes switch (type) { 38476daed103193a1756535d1f59b165e98e1d17445Chris Banes case TYPE_TOUCH: 38576daed103193a1756535d1f59b165e98e1d17445Chris Banes return mNestedScrollingParentTouch; 38676daed103193a1756535d1f59b165e98e1d17445Chris Banes case TYPE_NON_TOUCH: 38776daed103193a1756535d1f59b165e98e1d17445Chris Banes return mNestedScrollingParentNonTouch; 38876daed103193a1756535d1f59b165e98e1d17445Chris Banes } 38976daed103193a1756535d1f59b165e98e1d17445Chris Banes return null; 39076daed103193a1756535d1f59b165e98e1d17445Chris Banes } 39176daed103193a1756535d1f59b165e98e1d17445Chris Banes 39276daed103193a1756535d1f59b165e98e1d17445Chris Banes private void setNestedScrollingParentForType(@NestedScrollType int type, ViewParent p) { 39376daed103193a1756535d1f59b165e98e1d17445Chris Banes switch (type) { 39476daed103193a1756535d1f59b165e98e1d17445Chris Banes case TYPE_TOUCH: 39576daed103193a1756535d1f59b165e98e1d17445Chris Banes mNestedScrollingParentTouch = p; 39676daed103193a1756535d1f59b165e98e1d17445Chris Banes break; 39776daed103193a1756535d1f59b165e98e1d17445Chris Banes case TYPE_NON_TOUCH: 39876daed103193a1756535d1f59b165e98e1d17445Chris Banes mNestedScrollingParentNonTouch = p; 39976daed103193a1756535d1f59b165e98e1d17445Chris Banes break; 40076daed103193a1756535d1f59b165e98e1d17445Chris Banes } 40176daed103193a1756535d1f59b165e98e1d17445Chris Banes } 4021fcce4485ef99aca928ebfb877859c5ecd47716cAdam Powell} 403