1 /* 2 * Copyright 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package androidx.core.view; 18 19 import android.os.Build; 20 import android.util.Log; 21 import android.view.MotionEvent; 22 import android.view.VelocityTracker; 23 import android.view.View; 24 import android.view.ViewConfiguration; 25 import android.view.ViewParent; 26 import android.view.accessibility.AccessibilityEvent; 27 28 import androidx.annotation.RequiresApi; 29 30 import org.jspecify.annotations.NonNull; 31 32 /** 33 * Helper for accessing features in {@link ViewParent}. 34 */ 35 public final class ViewParentCompat { 36 37 private static final String TAG = "ViewParentCompat"; 38 private static int[] sTempNestedScrollConsumed; 39 40 /* 41 * Hide the constructor. 42 */ ViewParentCompat()43 private ViewParentCompat() {} 44 45 /** 46 * Called by a child to request from its parent to send an {@link AccessibilityEvent}. 47 * The child has already populated a record for itself in the event and is delegating 48 * to its parent to send the event. The parent can optionally add a record for itself. 49 * <p> 50 * Note: An accessibility event is fired by an individual view which populates the 51 * event with a record for its state and requests from its parent to perform 52 * the sending. The parent can optionally add a record for itself before 53 * dispatching the request to its parent. A parent can also choose not to 54 * respect the request for sending the event. The accessibility event is sent 55 * by the topmost view in the view tree.</p> 56 * 57 * @param parent The parent whose method to invoke. 58 * @param child The child which requests sending the event. 59 * @param event The event to be sent. 60 * @return True if the event was sent. 61 * 62 * @deprecated Use {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)} 63 * directly. 64 */ 65 @androidx.annotation.ReplaceWith(expression = "parent.requestSendAccessibilityEvent(child, event)") 66 @Deprecated requestSendAccessibilityEvent( ViewParent parent, View child, AccessibilityEvent event)67 public static boolean requestSendAccessibilityEvent( 68 ViewParent parent, View child, AccessibilityEvent event) { 69 return parent.requestSendAccessibilityEvent(child, event); 70 } 71 72 /** 73 * React to a descendant view initiating a nestable scroll operation, claiming the 74 * nested scroll operation if appropriate. 75 * 76 * <p>This version of the method just calls 77 * {@link #onStartNestedScroll(ViewParent, View, View, int, int)} using the touch input type. 78 * </p> 79 * 80 * @param parent ViewParent that contains the child view. 81 * @param child Direct child of this ViewParent containing target 82 * @param target View that initiated the nested scroll 83 * @param nestedScrollAxes Flags consisting of {@link ViewCompat#SCROLL_AXIS_HORIZONTAL}, 84 * {@link ViewCompat#SCROLL_AXIS_VERTICAL} or both 85 * @return true if this ViewParent accepts the nested scroll operation 86 */ onStartNestedScroll(@onNull ViewParent parent, @NonNull View child, @NonNull View target, int nestedScrollAxes)87 public static boolean onStartNestedScroll(@NonNull ViewParent parent, @NonNull View child, 88 @NonNull View target, int nestedScrollAxes) { 89 return onStartNestedScroll(parent, child, target, nestedScrollAxes, ViewCompat.TYPE_TOUCH); 90 } 91 92 /** 93 * React to the successful claiming of a nested scroll operation. 94 * 95 * <p>This version of the method just calls 96 * {@link #onNestedScrollAccepted(ViewParent, View, View, int, int)} using the touch input type. 97 * </p> 98 * 99 * @param parent ViewParent that contains the child view. 100 * @param child Direct child of this ViewParent containing target 101 * @param target View that initiated the nested scroll 102 * @param nestedScrollAxes Flags consisting of {@link ViewCompat#SCROLL_AXIS_HORIZONTAL}, 103 * {@link ViewCompat#SCROLL_AXIS_VERTICAL} or both 104 */ onNestedScrollAccepted(@onNull ViewParent parent, @NonNull View child, @NonNull View target, int nestedScrollAxes)105 public static void onNestedScrollAccepted(@NonNull ViewParent parent, @NonNull View child, 106 @NonNull View target, int nestedScrollAxes) { 107 onNestedScrollAccepted(parent, child, target, nestedScrollAxes, ViewCompat.TYPE_TOUCH); 108 } 109 110 /** 111 * React to a nested scroll operation ending. 112 * 113 * <p>This version of the method just calls {@link #onStopNestedScroll(ViewParent, View, int)} 114 * using the touch input type.</p> 115 * 116 * @param parent ViewParent that contains the target view. 117 * @param target View that initiated the nested scroll 118 */ onStopNestedScroll(@onNull ViewParent parent, @NonNull View target)119 public static void onStopNestedScroll(@NonNull ViewParent parent, @NonNull View target) { 120 onStopNestedScroll(parent, target, ViewCompat.TYPE_TOUCH); 121 } 122 123 /** 124 * React to a nested scroll in progress. 125 * 126 * <p>This version of the method just calls 127 * {@link #onNestedScroll(ViewParent, View, int, int, int, int, int)} using the touch input 128 * type. 129 * 130 * @param parent ViewParent that contains the target view. 131 * @param target The descendent view controlling the nested scroll 132 * @param dxConsumed Horizontal scroll distance in pixels already consumed by target 133 * @param dyConsumed Vertical scroll distance in pixels already consumed by target 134 * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by target 135 * @param dyUnconsumed Vertical scroll distance in pixels not consumed by target 136 */ onNestedScroll(@onNull ViewParent parent, @NonNull View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed)137 public static void onNestedScroll(@NonNull ViewParent parent, @NonNull View target, 138 int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) { 139 onNestedScroll(parent, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, 140 ViewCompat.TYPE_TOUCH, getTempNestedScrollConsumed()); 141 } 142 143 /** 144 * React to a nested scroll in progress. 145 * 146 * <p>This method will be called when the ViewParent's current nested scrolling child view 147 * dispatches a nested scroll event. To receive calls to this method the ViewParent must have 148 * previously returned <code>true</code> for a call to 149 * {@link #onStartNestedScroll(ViewParent, View, View, int, int)}.</p> 150 * 151 * <p>Both the consumed and unconsumed portions of the scroll distance are reported to the 152 * ViewParent. An implementation may choose to use the consumed portion to match or chase scroll 153 * position of multiple child elements, for example. The unconsumed portion may be used to 154 * allow continuous dragging of multiple scrolling or draggable elements, such as scrolling 155 * a list within a vertical drawer where the drawer begins dragging once the edge of inner 156 * scrolling content is reached.</p> 157 * 158 * @param parent ViewParent that contains the target view. 159 * @param target The descendant view controlling the nested scroll 160 * @param dxConsumed Horizontal scroll distance in pixels already consumed by target 161 * @param dyConsumed Vertical scroll distance in pixels already consumed by target 162 * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by target 163 * @param dyUnconsumed Vertical scroll distance in pixels not consumed by target 164 * @param type the type of input which cause this scroll event 165 */ onNestedScroll(@onNull ViewParent parent, @NonNull View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int type)166 public static void onNestedScroll(@NonNull ViewParent parent, @NonNull View target, 167 int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int type) { 168 onNestedScroll(parent, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, 169 type, getTempNestedScrollConsumed()); 170 } 171 172 /** 173 * React to a nested scroll in progress before the target view consumes a portion of the scroll. 174 * 175 * <p>This version of the method just calls 176 * {@link #onNestedPreScroll(ViewParent, View, int, int, int[], int)} using the touch input 177 * type.</p> 178 * 179 * @param parent ViewParent that contains the target view. 180 * @param target View that initiated the nested scroll 181 * @param dx Horizontal scroll distance in pixels 182 * @param dy Vertical scroll distance in pixels 183 * @param consumed Output. The horizontal and vertical scroll distance consumed by this parent 184 */ onNestedPreScroll(@onNull ViewParent parent, @NonNull View target, int dx, int dy, int @NonNull [] consumed)185 public static void onNestedPreScroll(@NonNull ViewParent parent, @NonNull View target, int dx, 186 int dy, int @NonNull [] consumed) { 187 onNestedPreScroll(parent, target, dx, dy, consumed, ViewCompat.TYPE_TOUCH); 188 } 189 190 /** 191 * React to a descendant view initiating a nestable scroll operation, claiming the 192 * nested scroll operation if appropriate. 193 * 194 * <p>This method will be called in response to a descendant view invoking 195 * {@link ViewCompat#startNestedScroll(View, int)}. Each parent up the view hierarchy will be 196 * given an opportunity to respond and claim the nested scrolling operation by returning 197 * <code>true</code>.</p> 198 * 199 * <p>This method may be overridden by ViewParent implementations to indicate when the view 200 * is willing to support a nested scrolling operation that is about to begin. If it returns 201 * true, this ViewParent will become the target view's nested scrolling parent for the duration 202 * of the scroll operation in progress. When the nested scroll is finished this ViewParent 203 * will receive a call to {@link #onStopNestedScroll(ViewParent, View, int)}. 204 * </p> 205 * 206 * @param parent ViewParent that contains the child view. 207 * @param child Direct child of this ViewParent containing target 208 * @param target View that initiated the nested scroll 209 * @param nestedScrollAxes Flags consisting of {@link ViewCompat#SCROLL_AXIS_HORIZONTAL}, 210 * {@link ViewCompat#SCROLL_AXIS_VERTICAL} or both 211 * @param type the type of input which cause this scroll event 212 * @return true if this ViewParent accepts the nested scroll operation 213 */ 214 @SuppressWarnings("RedundantCast") // Intentionally invoking interface method. onStartNestedScroll(@onNull ViewParent parent, @NonNull View child, @NonNull View target, int nestedScrollAxes, int type)215 public static boolean onStartNestedScroll(@NonNull ViewParent parent, @NonNull View child, 216 @NonNull View target, int nestedScrollAxes, int type) { 217 if (parent instanceof NestedScrollingParent2) { 218 // First try the NestedScrollingParent2 API 219 return ((NestedScrollingParent2) parent).onStartNestedScroll(child, target, 220 nestedScrollAxes, type); 221 } else if (type == ViewCompat.TYPE_TOUCH) { 222 // Else if the type is the default (touch), try the NestedScrollingParent API 223 if (Build.VERSION.SDK_INT >= 21) { 224 try { 225 return Api21Impl.onStartNestedScroll(parent, child, target, nestedScrollAxes); 226 } catch (AbstractMethodError e) { 227 Log.e(TAG, "ViewParent " + parent + " does not implement interface " 228 + "method onStartNestedScroll", e); 229 } 230 } else if (parent instanceof NestedScrollingParent) { 231 return ((NestedScrollingParent) parent).onStartNestedScroll(child, target, 232 nestedScrollAxes); 233 } 234 } 235 return false; 236 } 237 238 /** 239 * React to the successful claiming of a nested scroll operation. 240 * 241 * <p>This method will be called after 242 * {@link #onStartNestedScroll(ViewParent, View, View, int) onStartNestedScroll} returns true. 243 * It offers an opportunity for the view and its superclasses to perform initial configuration 244 * for the nested scroll. Implementations of this method should always call their superclass's 245 * implementation of this method if one is present.</p> 246 * 247 * @param parent ViewParent that contains the child view. 248 * @param child Direct child of this ViewParent containing target 249 * @param target View that initiated the nested scroll 250 * @param nestedScrollAxes Flags consisting of {@link ViewCompat#SCROLL_AXIS_HORIZONTAL}, 251 * {@link ViewCompat#SCROLL_AXIS_VERTICAL} or both 252 * @param type the type of input which cause this scroll event 253 * @see #onStartNestedScroll(ViewParent, View, View, int) 254 * @see #onStopNestedScroll(ViewParent, View, int) 255 */ 256 @SuppressWarnings("RedundantCast") // Intentionally invoking interface method. onNestedScrollAccepted(@onNull ViewParent parent, @NonNull View child, @NonNull View target, int nestedScrollAxes, int type)257 public static void onNestedScrollAccepted(@NonNull ViewParent parent, @NonNull View child, 258 @NonNull View target, int nestedScrollAxes, int type) { 259 if (parent instanceof NestedScrollingParent2) { 260 // First try the NestedScrollingParent2 API 261 ((NestedScrollingParent2) parent).onNestedScrollAccepted(child, target, 262 nestedScrollAxes, type); 263 } else if (type == ViewCompat.TYPE_TOUCH) { 264 // Else if the type is the default (touch), try the NestedScrollingParent API 265 if (Build.VERSION.SDK_INT >= 21) { 266 try { 267 Api21Impl.onNestedScrollAccepted(parent, child, target, nestedScrollAxes); 268 } catch (AbstractMethodError e) { 269 Log.e(TAG, "ViewParent " + parent + " does not implement interface " 270 + "method onNestedScrollAccepted", e); 271 } 272 } else if (parent instanceof NestedScrollingParent) { 273 ((NestedScrollingParent) parent).onNestedScrollAccepted(child, target, 274 nestedScrollAxes); 275 } 276 } 277 } 278 279 /** 280 * React to a nested scroll operation ending. 281 * 282 * <p>Perform cleanup after a nested scrolling operation. 283 * This method will be called when a nested scroll stops, for example when a nested touch 284 * scroll ends with a {@link MotionEvent#ACTION_UP} or {@link MotionEvent#ACTION_CANCEL} event. 285 * Implementations of this method should always call their superclass's implementation of this 286 * method if one is present.</p> 287 * 288 * @param parent ViewParent that contains the target view. 289 * @param target View that initiated the nested scroll 290 * @param type the type of input which cause this scroll event 291 */ 292 @SuppressWarnings("RedundantCast") // Intentionally invoking interface method. onStopNestedScroll(@onNull ViewParent parent, @NonNull View target, int type)293 public static void onStopNestedScroll(@NonNull ViewParent parent, @NonNull View target, 294 int type) { 295 if (parent instanceof NestedScrollingParent2) { 296 // First try the NestedScrollingParent2 API 297 ((NestedScrollingParent2) parent).onStopNestedScroll(target, type); 298 } else if (type == ViewCompat.TYPE_TOUCH) { 299 // Else if the type is the default (touch), try the NestedScrollingParent API 300 if (Build.VERSION.SDK_INT >= 21) { 301 try { 302 Api21Impl.onStopNestedScroll(parent, target); 303 } catch (AbstractMethodError e) { 304 Log.e(TAG, "ViewParent " + parent + " does not implement interface " 305 + "method onStopNestedScroll", e); 306 } 307 } else if (parent instanceof NestedScrollingParent) { 308 ((NestedScrollingParent) parent).onStopNestedScroll(target); 309 } 310 } 311 } 312 313 /** 314 * React to a nested scroll in progress. 315 * 316 * <p>This method will be called when the ViewParent's current nested scrolling child view 317 * dispatches a nested scroll event. To receive calls to this method the ViewParent must have 318 * previously returned <code>true</code> for a call to 319 * {@link #onStartNestedScroll(ViewParent, View, View, int, int)}.</p> 320 * 321 * <p>Both the consumed and unconsumed portions of the scroll distance are reported to the 322 * ViewParent. An implementation may choose to use the consumed portion to match or chase scroll 323 * position of multiple child elements, for example. The unconsumed portion may be used to 324 * allow continuous dragging of multiple scrolling or draggable elements, such as scrolling 325 * a list within a vertical drawer where the drawer begins dragging once the edge of inner 326 * scrolling content is reached.</p> 327 * 328 * @param parent ViewParent that contains the target view. 329 * @param target The descendent view controlling the nested scroll 330 * @param dxConsumed Horizontal scroll distance in pixels already consumed by target 331 * @param dyConsumed Vertical scroll distance in pixels already consumed by target 332 * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by target 333 * @param dyUnconsumed Vertical scroll distance in pixels not consumed by target 334 * @param type the type of input which cause this scroll event 335 * @param consumed Output. If not null, upon this method returning, will contain the scroll 336 * distances consumed by this nested scrolling parent and the scroll distances 337 * consumed by any other parent up the view hierarchy. 338 */ onNestedScroll(@onNull ViewParent parent, @NonNull View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int type, int @NonNull [] consumed)339 public static void onNestedScroll(@NonNull ViewParent parent, @NonNull View target, 340 int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int type, 341 int @NonNull [] consumed) { 342 343 if (parent instanceof NestedScrollingParent3) { 344 ((NestedScrollingParent3) parent).onNestedScroll(target, dxConsumed, dyConsumed, 345 dxUnconsumed, dyUnconsumed, type, consumed); 346 } else { 347 // If we are calling anything less than NestedScrollingParent3, add the unconsumed 348 // distances to the consumed parameter so calling NestedScrollingChild3 implementations 349 // are told the entire scroll distance was consumed (for backwards compat). 350 consumed[0] += dxUnconsumed; 351 consumed[1] += dyUnconsumed; 352 353 if (parent instanceof NestedScrollingParent2) { 354 ((NestedScrollingParent2) parent).onNestedScroll(target, dxConsumed, dyConsumed, 355 dxUnconsumed, dyUnconsumed, type); 356 } else if (type == ViewCompat.TYPE_TOUCH) { 357 // Else if the type is the default (touch), try the NestedScrollingParent API 358 if (Build.VERSION.SDK_INT >= 21) { 359 try { 360 Api21Impl.onNestedScroll(parent, target, dxConsumed, dyConsumed, 361 dxUnconsumed, dyUnconsumed); 362 } catch (AbstractMethodError e) { 363 Log.e(TAG, "ViewParent " + parent + " does not implement interface " 364 + "method onNestedScroll", e); 365 } 366 } else if (parent instanceof NestedScrollingParent) { 367 ((NestedScrollingParent) parent).onNestedScroll(target, dxConsumed, dyConsumed, 368 dxUnconsumed, dyUnconsumed); 369 } 370 } 371 } 372 } 373 374 /** 375 * React to a nested scroll in progress before the target view consumes a portion of the scroll. 376 * 377 * <p>When working with nested scrolling often the parent view may want an opportunity 378 * to consume the scroll before the nested scrolling child does. An example of this is a 379 * drawer that contains a scrollable list. The user will want to be able to scroll the list 380 * fully into view before the list itself begins scrolling.</p> 381 * 382 * <p><code>onNestedPreScroll</code> is called when a nested scrolling child invokes 383 * {@link ViewCompat#dispatchNestedPreScroll(View, int, int, int[], int[])}. The implementation 384 * should report how any pixels of the scroll reported by dx, dy were consumed in the 385 * <code>consumed</code> array. Index 0 corresponds to dx and index 1 corresponds to dy. 386 * This parameter will never be null. Initial values for consumed[0] and consumed[1] 387 * will always be 0.</p> 388 * 389 * @param parent ViewParent that contains the target view. 390 * @param target View that initiated the nested scroll 391 * @param dx Horizontal scroll distance in pixels 392 * @param dy Vertical scroll distance in pixels 393 * @param consumed Output. The horizontal and vertical scroll distance consumed by this parent 394 * @param type the type of input which cause this scroll event 395 */ 396 @SuppressWarnings("RedundantCast") // Intentionally invoking interface method. onNestedPreScroll(@onNull ViewParent parent, @NonNull View target, int dx, int dy, int @NonNull [] consumed, int type)397 public static void onNestedPreScroll(@NonNull ViewParent parent, @NonNull View target, int dx, 398 int dy, int @NonNull [] consumed, int type) { 399 if (parent instanceof NestedScrollingParent2) { 400 // First try the NestedScrollingParent2 API 401 ((NestedScrollingParent2) parent).onNestedPreScroll(target, dx, dy, consumed, type); 402 } else if (type == ViewCompat.TYPE_TOUCH) { 403 // Else if the type is the default (touch), try the NestedScrollingParent API 404 if (Build.VERSION.SDK_INT >= 21) { 405 try { 406 Api21Impl.onNestedPreScroll(parent, target, dx, dy, consumed); 407 } catch (AbstractMethodError e) { 408 Log.e(TAG, "ViewParent " + parent + " does not implement interface " 409 + "method onNestedPreScroll", e); 410 } 411 } else if (parent instanceof NestedScrollingParent) { 412 ((NestedScrollingParent) parent).onNestedPreScroll(target, dx, dy, consumed); 413 } 414 } 415 } 416 417 /** 418 * Request a fling from a nested scroll. 419 * 420 * <p>This method signifies that a nested scrolling child has detected suitable conditions 421 * for a fling. Generally this means that a touch scroll has ended with a 422 * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds 423 * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity} 424 * along a scrollable axis.</p> 425 * 426 * <p>If a nested scrolling child view would normally fling but it is at the edge of 427 * its own content, it can use this method to delegate the fling to its nested scrolling 428 * parent instead. The parent may optionally consume the fling or observe a child fling.</p> 429 * 430 * @param parent ViewParent that contains the target view. 431 * @param target View that initiated the nested scroll 432 * @param velocityX Horizontal velocity in pixels per second 433 * @param velocityY Vertical velocity in pixels per second 434 * @param consumed true if the child consumed the fling, false otherwise 435 * @return true if this parent consumed or otherwise reacted to the fling 436 */ 437 @SuppressWarnings("RedundantCast") // Intentionally invoking interface method. onNestedFling(@onNull ViewParent parent, @NonNull View target, float velocityX, float velocityY, boolean consumed)438 public static boolean onNestedFling(@NonNull ViewParent parent, @NonNull View target, 439 float velocityX, float velocityY, boolean consumed) { 440 if (Build.VERSION.SDK_INT >= 21) { 441 try { 442 return Api21Impl.onNestedFling(parent, target, velocityX, velocityY, consumed); 443 } catch (AbstractMethodError e) { 444 Log.e(TAG, "ViewParent " + parent + " does not implement interface " 445 + "method onNestedFling", e); 446 } 447 } else if (parent instanceof NestedScrollingParent) { 448 return ((NestedScrollingParent) parent).onNestedFling(target, velocityX, velocityY, 449 consumed); 450 } 451 return false; 452 } 453 454 /** 455 * React to a nested fling before the target view consumes it. 456 * 457 * <p>This method siginfies that a nested scrolling child has detected a fling with the given 458 * velocity along each axis. Generally this means that a touch scroll has ended with a 459 * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds 460 * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity} 461 * along a scrollable axis.</p> 462 * 463 * <p>If a nested scrolling parent is consuming motion as part of a 464 * {@link #onNestedPreScroll(ViewParent, View, int, int, int[]) pre-scroll}, it may be 465 * appropriate for it to also consume the pre-fling to complete that same motion. By returning 466 * <code>true</code> from this method, the parent indicates that the child should not 467 * fling its own internal content as well.</p> 468 * 469 * @param parent ViewParent that contains the target view. 470 * @param target View that initiated the nested scroll 471 * @param velocityX Horizontal velocity in pixels per second 472 * @param velocityY Vertical velocity in pixels per second 473 * @return true if this parent consumed the fling ahead of the target view 474 */ 475 @SuppressWarnings("RedundantCast") // Intentionally invoking interface method. onNestedPreFling(@onNull ViewParent parent, @NonNull View target, float velocityX, float velocityY)476 public static boolean onNestedPreFling(@NonNull ViewParent parent, @NonNull View target, 477 float velocityX, float velocityY) { 478 if (Build.VERSION.SDK_INT >= 21) { 479 try { 480 return Api21Impl.onNestedPreFling(parent, target, velocityX, velocityY); 481 } catch (AbstractMethodError e) { 482 Log.e(TAG, "ViewParent " + parent + " does not implement interface " 483 + "method onNestedPreFling", e); 484 } 485 } else if (parent instanceof NestedScrollingParent) { 486 return ((NestedScrollingParent) parent).onNestedPreFling(target, velocityX, 487 velocityY); 488 } 489 return false; 490 } 491 492 /** 493 * Notifies a view parent that the accessibility state of one of its 494 * descendants has changed and that the structure of the subtree is 495 * different. 496 * 497 * @param parent ViewParent that contains the target view. 498 * @param child The direct child whose subtree has changed. 499 * @param source The descendant view that changed. 500 * @param changeType A bit mask of the types of changes that occurred. One 501 * or more of: 502 * <ul> 503 * <li>{@link AccessibilityEvent#CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION} 504 * <li>{@link AccessibilityEvent#CONTENT_CHANGE_TYPE_SUBTREE} 505 * <li>{@link AccessibilityEvent#CONTENT_CHANGE_TYPE_TEXT} 506 * <li>{@link AccessibilityEvent#CONTENT_CHANGE_TYPE_UNDEFINED} 507 * </ul> 508 * @deprecated Call {@link ViewParent#notifySubtreeAccessibilityStateChanged()} directly. 509 */ 510 @Deprecated 511 @androidx.annotation.ReplaceWith(expression = "parent.notifySubtreeAccessibilityStateChanged(child, source, changeType)") notifySubtreeAccessibilityStateChanged(@onNull ViewParent parent, @NonNull View child, @NonNull View source, int changeType)512 public static void notifySubtreeAccessibilityStateChanged(@NonNull ViewParent parent, 513 @NonNull View child, @NonNull View source, int changeType) { 514 parent.notifySubtreeAccessibilityStateChanged(child, source, changeType); 515 } 516 getTempNestedScrollConsumed()517 private static int[] getTempNestedScrollConsumed() { 518 if (sTempNestedScrollConsumed == null) { 519 sTempNestedScrollConsumed = new int[2]; 520 } else { 521 sTempNestedScrollConsumed[0] = 0; 522 sTempNestedScrollConsumed[1] = 0; 523 } 524 return sTempNestedScrollConsumed; 525 } 526 527 @RequiresApi(21) 528 static class Api21Impl { Api21Impl()529 private Api21Impl() { 530 // This class is not instantiable. 531 } 532 onStartNestedScroll(ViewParent viewParent, View view, View view1, int i)533 static boolean onStartNestedScroll(ViewParent viewParent, View view, View view1, int i) { 534 return viewParent.onStartNestedScroll(view, view1, i); 535 } 536 onNestedScrollAccepted(ViewParent viewParent, View view, View view1, int i)537 static void onNestedScrollAccepted(ViewParent viewParent, View view, View view1, int i) { 538 viewParent.onNestedScrollAccepted(view, view1, i); 539 } 540 onStopNestedScroll(ViewParent viewParent, View view)541 static void onStopNestedScroll(ViewParent viewParent, View view) { 542 viewParent.onStopNestedScroll(view); 543 } 544 onNestedScroll(ViewParent viewParent, View view, int i, int i1, int i2, int i3)545 static void onNestedScroll(ViewParent viewParent, View view, int i, int i1, int i2, 546 int i3) { 547 viewParent.onNestedScroll(view, i, i1, i2, i3); 548 } 549 onNestedPreScroll(ViewParent viewParent, View view, int i, int i1, int[] ints)550 static void onNestedPreScroll(ViewParent viewParent, View view, int i, int i1, int[] ints) { 551 viewParent.onNestedPreScroll(view, i, i1, ints); 552 } 553 onNestedFling(ViewParent viewParent, View view, float v, float v1, boolean b)554 static boolean onNestedFling(ViewParent viewParent, View view, float v, float v1, 555 boolean b) { 556 return viewParent.onNestedFling(view, v, v1, b); 557 } 558 onNestedPreFling(ViewParent viewParent, View view, float v, float v1)559 static boolean onNestedPreFling(ViewParent viewParent, View view, float v, float v1) { 560 return viewParent.onNestedPreFling(view, v, v1); 561 } 562 } 563 } 564