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