NestedScrollingChildHelper.java revision ac5fe7c617c66850fff75a9fce9979c6e5674b0f
1ce796e78a57018f186b062199c75d94545318acaPablo Ceballos/* 2ce796e78a57018f186b062199c75d94545318acaPablo Ceballos * Copyright 2018 The Android Open Source Project 3ce796e78a57018f186b062199c75d94545318acaPablo Ceballos * 4ce796e78a57018f186b062199c75d94545318acaPablo Ceballos * Licensed under the Apache License, Version 2.0 (the "License"); 5ce796e78a57018f186b062199c75d94545318acaPablo Ceballos * you may not use this file except in compliance with the License. 6ce796e78a57018f186b062199c75d94545318acaPablo Ceballos * You may obtain a copy of the License at 7ce796e78a57018f186b062199c75d94545318acaPablo Ceballos * 8ce796e78a57018f186b062199c75d94545318acaPablo Ceballos * http://www.apache.org/licenses/LICENSE-2.0 9ce796e78a57018f186b062199c75d94545318acaPablo Ceballos * 10ce796e78a57018f186b062199c75d94545318acaPablo Ceballos * Unless required by applicable law or agreed to in writing, software 11ce796e78a57018f186b062199c75d94545318acaPablo Ceballos * distributed under the License is distributed on an "AS IS" BASIS, 12ce796e78a57018f186b062199c75d94545318acaPablo Ceballos * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ce796e78a57018f186b062199c75d94545318acaPablo Ceballos * See the License for the specific language governing permissions and 14ce796e78a57018f186b062199c75d94545318acaPablo Ceballos * limitations under the License. 15ce796e78a57018f186b062199c75d94545318acaPablo Ceballos */ 16ce796e78a57018f186b062199c75d94545318acaPablo Ceballos 17ce796e78a57018f186b062199c75d94545318acaPablo Ceballos 18ce796e78a57018f186b062199c75d94545318acaPablo Ceballospackage androidx.core.view; 19ce796e78a57018f186b062199c75d94545318acaPablo Ceballos 20d6927fb1143398370c0885844bfb58923ef740b7Brian Andersonimport static androidx.core.view.ViewCompat.TYPE_NON_TOUCH; 21ce796e78a57018f186b062199c75d94545318acaPablo Ceballosimport static androidx.core.view.ViewCompat.TYPE_TOUCH; 22d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson 23d6927fb1143398370c0885844bfb58923ef740b7Brian Andersonimport androidx.annotation.NonNull; 24d6927fb1143398370c0885844bfb58923ef740b7Brian Andersonimport androidx.annotation.Nullable; 25d6927fb1143398370c0885844bfb58923ef740b7Brian Andersonimport androidx.core.view.ViewCompat.NestedScrollType; 263890c3995c4a52439844faeb80b5503d42b977d8Brian Andersonimport androidx.core.view.ViewCompat.ScrollAxis; 273890c3995c4a52439844faeb80b5503d42b977d8Brian Andersonimport android.view.View; 28ce796e78a57018f186b062199c75d94545318acaPablo Ceballosimport android.view.ViewParent; 29ce796e78a57018f186b062199c75d94545318acaPablo Ceballos 30ce796e78a57018f186b062199c75d94545318acaPablo Ceballos/** 31d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson * Helper class for implementing nested scrolling child views compatible with Android platform 32d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson * versions earlier than Android 5.0 Lollipop (API 21). 333890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * 34d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson * <p>{@link android.view.View View} subclasses should instantiate a final instance of this 35d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson * class as a field at construction. For each <code>View</code> method that has a matching 36d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson * method signature in this class, delegate the operation to the helper instance in an overridden 373890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * method implementation. This implements the standard framework policy for nested scrolling.</p> 383890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * 39069b365163470d2736eb6f591c354d208b5da23bBrian Anderson * <p>Views invoking nested scrolling functionality should always do so from the relevant 403890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * {@link androidx.core.view.ViewCompat}, {@link androidx.core.view.ViewGroupCompat} or 41069b365163470d2736eb6f591c354d208b5da23bBrian Anderson * {@link androidx.core.view.ViewParentCompat} compatibility 423890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * shim static methods. This ensures interoperability with nested scrolling views on Android 433890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * 5.0 Lollipop and newer.</p> 443890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson */ 453890c3995c4a52439844faeb80b5503d42b977d8Brian Andersonpublic class NestedScrollingChildHelper { 463890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson private ViewParent mNestedScrollingParentTouch; 473890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson private ViewParent mNestedScrollingParentNonTouch; 483890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson private final View mView; 49ce796e78a57018f186b062199c75d94545318acaPablo Ceballos private boolean mIsNestedScrollingEnabled; 50ce796e78a57018f186b062199c75d94545318acaPablo Ceballos private int[] mTempNestedScrollConsumed; 51d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson 52d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson /** 53d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson * Construct a new helper for a given view. 543890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson */ 553890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson public NestedScrollingChildHelper(@NonNull View view) { 563890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson mView = view; 573890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson } 583890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson 593890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson /** 603890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * Enable nested scrolling. 613890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * 623890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass 633890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * method/{@link androidx.core.view.NestedScrollingChild} interface method with the same 643890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * signature to implement the standard policy.</p> 65d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson * 66d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson * @param enabled true to enable nested scrolling dispatch from this view, false otherwise 67d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson */ 683890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson public void setNestedScrollingEnabled(boolean enabled) { 693890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson if (mIsNestedScrollingEnabled) { 703890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson ViewCompat.stopNestedScroll(mView); 713890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson } 72d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson mIsNestedScrollingEnabled = enabled; 73d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson } 74d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson 75d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson /** 76d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson * Check if nested scrolling is enabled for this view. 77d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson * 78d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass 79d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson * method/{@link androidx.core.view.NestedScrollingChild} interface method with the same 803890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * signature to implement the standard policy.</p> 81d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson * 82d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson * @return true if nested scrolling is enabled for this view 83d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson */ 84d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson public boolean isNestedScrollingEnabled() { 85d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson return mIsNestedScrollingEnabled; 86d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson } 87d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson 88d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson /** 89d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson * Check if this view has a nested scrolling parent view currently receiving events for 90d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson * a nested scroll in progress with the type of touch. 91d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson * 92d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass 93d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson * method/{@link androidx.core.view.NestedScrollingChild} interface method with the same 94d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson * signature to implement the standard policy.</p> 95d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson * 96d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson * @return true if this view has a nested scrolling parent, false otherwise 97d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson */ 98d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson public boolean hasNestedScrollingParent() { 99d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson return hasNestedScrollingParent(TYPE_TOUCH); 100d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson } 101d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson 1023890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson /** 1033890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * Check if this view has a nested scrolling parent view currently receiving events for 1043890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * a nested scroll in progress with the given type. 1053890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * 1063890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass 1073890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * method/{@link androidx.core.view.NestedScrollingChild} interface method with the same 1083890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * signature to implement the standard policy.</p> 1093890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * 1103890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * @return true if this view has a nested scrolling parent, false otherwise 1113890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson */ 1123890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson public boolean hasNestedScrollingParent(@NestedScrollType int type) { 1133890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson return getNestedScrollingParentForType(type) != null; 1143890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson } 1153890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson 1163890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson /** 1173890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * Start a new nested scroll for this view. 1183890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * 1193890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass 1203890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * method/{@link androidx.core.view.NestedScrollingChild} interface method with the same 1213890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * signature to implement the standard policy.</p> 1223890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * 1233890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * @param axes Supported nested scroll axes. 1243890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * See {@link androidx.core.view.NestedScrollingChild#startNestedScroll(int)}. 1253890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * @return true if a cooperating parent view was found and nested scrolling started successfully 1263890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson */ 1273890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson public boolean startNestedScroll(@ScrollAxis int axes) { 1283890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson return startNestedScroll(axes, TYPE_TOUCH); 1293890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson } 1303890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson 1313890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson /** 1323890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * Start a new nested scroll for this view. 1333890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * 1343890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass 135d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson * method/{@link androidx.core.view.NestedScrollingChild2} interface method with the same 136d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson * signature to implement the standard policy.</p> 137d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson * 138d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson * @param axes Supported nested scroll axes. 139d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson * See {@link androidx.core.view.NestedScrollingChild2#startNestedScroll(int, 140d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson * int)}. 141d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson * @return true if a cooperating parent view was found and nested scrolling started successfully 142d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson */ 1433890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson public boolean startNestedScroll(@ScrollAxis int axes, @NestedScrollType int type) { 1443890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson if (hasNestedScrollingParent(type)) { 1453890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson // Already in progress 146d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson return true; 1473890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson } 1483890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson if (isNestedScrollingEnabled()) { 1493890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson ViewParent p = mView.getParent(); 1503890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson View child = mView; 1513890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson while (p != null) { 1523890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson if (ViewParentCompat.onStartNestedScroll(p, child, mView, axes, type)) { 1533890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson setNestedScrollingParentForType(type, p); 1543890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson ViewParentCompat.onNestedScrollAccepted(p, child, mView, axes, type); 1553890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson return true; 1563890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson } 1573890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson if (p instanceof View) { 1583890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson child = (View) p; 1593890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson } 1603890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson p = p.getParent(); 1613890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson } 1623890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson } 1633890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson return false; 1643890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson } 1653890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson 1663890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson /** 1673890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * Stop a nested scroll in progress. 168d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson * 1693890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass 1703890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * method/{@link androidx.core.view.NestedScrollingChild} interface method with the same 1713890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * signature to implement the standard policy.</p> 1723890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson */ 1733890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson public void stopNestedScroll() { 1743890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson stopNestedScroll(TYPE_TOUCH); 175d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson } 176d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson 177d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson /** 178d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson * Stop a nested scroll in progress. 179d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson * 180d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass 181d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson * method/{@link androidx.core.view.NestedScrollingChild2} interface method with the same 1823890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * signature to implement the standard policy.</p> 1833890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson */ 184d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson public void stopNestedScroll(@NestedScrollType int type) { 1853890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson ViewParent parent = getNestedScrollingParentForType(type); 186d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson if (parent != null) { 187d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson ViewParentCompat.onStopNestedScroll(parent, mView, type); 188d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson setNestedScrollingParentForType(type, null); 189d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson } 190d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson } 191d6927fb1143398370c0885844bfb58923ef740b7Brian Anderson 1923890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson /** 1933890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * Dispatch one step of a nested scrolling operation to the current nested scrolling parent. 1943890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * 1953890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass 1963890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * method/{@link androidx.core.view.NestedScrollingChild} interface method with the same 1973890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * signature to implement the standard policy.</p> 1983890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * 1993890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * @return true if the parent consumed any of the nested scroll 2003890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson */ 2013890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, 2023890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson int dxUnconsumed, int dyUnconsumed, @Nullable int[] offsetInWindow) { 2033890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson return dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, 2043890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson offsetInWindow, TYPE_TOUCH); 2053890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson } 2063890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson 2073890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson /** 2083890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * Dispatch one step of a nested scrolling operation to the current nested scrolling parent. 2093890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * 2103890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass 2113890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * method/{@link androidx.core.view.NestedScrollingChild2} interface method with the same 2123890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * signature to implement the standard policy.</p> 2133890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * 2143890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * @return true if the parent consumed any of the nested scroll 2153890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson */ 2163890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, 2173890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson int dxUnconsumed, int dyUnconsumed, @Nullable int[] offsetInWindow, 2183890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson @NestedScrollType int type) { 2193890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson if (isNestedScrollingEnabled()) { 2203890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson final ViewParent parent = getNestedScrollingParentForType(type); 2213890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson if (parent == null) { 2223890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson return false; 2233890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson } 2243890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson 2253890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) { 2263890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson int startX = 0; 2273890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson int startY = 0; 2283890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson if (offsetInWindow != null) { 2293890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson mView.getLocationInWindow(offsetInWindow); 2303890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson startX = offsetInWindow[0]; 2313890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson startY = offsetInWindow[1]; 2323890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson } 2333890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson 2343890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson ViewParentCompat.onNestedScroll(parent, mView, dxConsumed, 2353890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson dyConsumed, dxUnconsumed, dyUnconsumed, type); 2367c3ba8aa288755fad78ddbabcee0ad5a0610ac1cBrian Anderson 2377c3ba8aa288755fad78ddbabcee0ad5a0610ac1cBrian Anderson if (offsetInWindow != null) { 2387c3ba8aa288755fad78ddbabcee0ad5a0610ac1cBrian Anderson mView.getLocationInWindow(offsetInWindow); 2393890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson offsetInWindow[0] -= startX; 2407c3ba8aa288755fad78ddbabcee0ad5a0610ac1cBrian Anderson offsetInWindow[1] -= startY; 2417c3ba8aa288755fad78ddbabcee0ad5a0610ac1cBrian Anderson } 2423890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson return true; 2433890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson } else if (offsetInWindow != null) { 2443890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson // No motion, no dispatch. Keep offsetInWindow up to date. 2453890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson offsetInWindow[0] = 0; 2463890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson offsetInWindow[1] = 0; 2473890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson } 2483890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson } 2493890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson return false; 2503890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson } 2513890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson 2523890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson /** 2533890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * Dispatch one step of a nested pre-scrolling operation to the current nested scrolling parent. 2543890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * 2553890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass 2563890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * method/{@link androidx.core.view.NestedScrollingChild} interface method with the same 2573890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * signature to implement the standard policy.</p> 2583890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * 2593890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * @return true if the parent consumed any of the nested scroll 2603890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson */ 2613890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson public boolean dispatchNestedPreScroll(int dx, int dy, @Nullable int[] consumed, 2623890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson @Nullable int[] offsetInWindow) { 2633890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson return dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow, TYPE_TOUCH); 2643890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson } 2653890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson 2663890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson /** 2673890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * Dispatch one step of a nested pre-scrolling operation to the current nested scrolling parent. 2683890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * 2693890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass 2703890c3995c4a52439844faeb80b5503d42b977d8Brian Anderson * method/{@link androidx.core.view.NestedScrollingChild2} interface method with the same 271ce796e78a57018f186b062199c75d94545318acaPablo Ceballos * signature to implement the standard policy.</p> 272ce796e78a57018f186b062199c75d94545318acaPablo Ceballos * 273 * @return true if the parent consumed any of the nested scroll 274 */ 275 public boolean dispatchNestedPreScroll(int dx, int dy, @Nullable int[] consumed, 276 @Nullable int[] offsetInWindow, @NestedScrollType int type) { 277 if (isNestedScrollingEnabled()) { 278 final ViewParent parent = getNestedScrollingParentForType(type); 279 if (parent == null) { 280 return false; 281 } 282 283 if (dx != 0 || dy != 0) { 284 int startX = 0; 285 int startY = 0; 286 if (offsetInWindow != null) { 287 mView.getLocationInWindow(offsetInWindow); 288 startX = offsetInWindow[0]; 289 startY = offsetInWindow[1]; 290 } 291 292 if (consumed == null) { 293 if (mTempNestedScrollConsumed == null) { 294 mTempNestedScrollConsumed = new int[2]; 295 } 296 consumed = mTempNestedScrollConsumed; 297 } 298 consumed[0] = 0; 299 consumed[1] = 0; 300 ViewParentCompat.onNestedPreScroll(parent, mView, dx, dy, consumed, type); 301 302 if (offsetInWindow != null) { 303 mView.getLocationInWindow(offsetInWindow); 304 offsetInWindow[0] -= startX; 305 offsetInWindow[1] -= startY; 306 } 307 return consumed[0] != 0 || consumed[1] != 0; 308 } else if (offsetInWindow != null) { 309 offsetInWindow[0] = 0; 310 offsetInWindow[1] = 0; 311 } 312 } 313 return false; 314 } 315 316 /** 317 * Dispatch a nested fling operation to the current nested scrolling parent. 318 * 319 * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass 320 * method/{@link androidx.core.view.NestedScrollingChild} interface method with the same 321 * signature to implement the standard policy.</p> 322 * 323 * @return true if the parent consumed the nested fling 324 */ 325 public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) { 326 if (isNestedScrollingEnabled()) { 327 ViewParent parent = getNestedScrollingParentForType(TYPE_TOUCH); 328 if (parent != null) { 329 return ViewParentCompat.onNestedFling(parent, mView, velocityX, 330 velocityY, consumed); 331 } 332 } 333 return false; 334 } 335 336 /** 337 * Dispatch a nested pre-fling operation to the current nested scrolling parent. 338 * 339 * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass 340 * method/{@link androidx.core.view.NestedScrollingChild} interface method with the same 341 * signature to implement the standard policy.</p> 342 * 343 * @return true if the parent consumed the nested fling 344 */ 345 public boolean dispatchNestedPreFling(float velocityX, float velocityY) { 346 if (isNestedScrollingEnabled()) { 347 ViewParent parent = getNestedScrollingParentForType(TYPE_TOUCH); 348 if (parent != null) { 349 return ViewParentCompat.onNestedPreFling(parent, mView, velocityX, 350 velocityY); 351 } 352 } 353 return false; 354 } 355 356 /** 357 * View subclasses should always call this method on their 358 * <code>NestedScrollingChildHelper</code> when detached from a window. 359 * 360 * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass 361 * method/{@link androidx.core.view.NestedScrollingChild} interface method with the same 362 * signature to implement the standard policy.</p> 363 */ 364 public void onDetachedFromWindow() { 365 ViewCompat.stopNestedScroll(mView); 366 } 367 368 /** 369 * Called when a nested scrolling child stops its current nested scroll operation. 370 * 371 * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass 372 * method/{@link androidx.core.view.NestedScrollingChild} interface method with the same 373 * signature to implement the standard policy.</p> 374 * 375 * @param child Child view stopping its nested scroll. This may not be a direct child view. 376 */ 377 public void onStopNestedScroll(@NonNull View child) { 378 ViewCompat.stopNestedScroll(mView); 379 } 380 381 private ViewParent getNestedScrollingParentForType(@NestedScrollType int type) { 382 switch (type) { 383 case TYPE_TOUCH: 384 return mNestedScrollingParentTouch; 385 case TYPE_NON_TOUCH: 386 return mNestedScrollingParentNonTouch; 387 } 388 return null; 389 } 390 391 private void setNestedScrollingParentForType(@NestedScrollType int type, ViewParent p) { 392 switch (type) { 393 case TYPE_TOUCH: 394 mNestedScrollingParentTouch = p; 395 break; 396 case TYPE_NON_TOUCH: 397 mNestedScrollingParentNonTouch = p; 398 break; 399 } 400 } 401} 402