From 0eeb93be959d7b13e879dae1226bb996280cf34c Mon Sep 17 00:00:00 2001 From: drrefactor Date: Wed, 16 Oct 2024 09:46:55 +0200 Subject: [PATCH] Do not track Android ScrollView scroll velocity if scroll changed outside gestures --- .../react/views/scroll/OnScrollDispatchHelper.kt | 16 ++++++++++++---- .../views/scroll/ReactHorizontalScrollView.java | 2 +- .../react/views/scroll/ReactScrollView.java | 2 +- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/OnScrollDispatchHelper.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/OnScrollDispatchHelper.kt index 42a0c2ca4acc..d01a98485193 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/OnScrollDispatchHelper.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/OnScrollDispatchHelper.kt @@ -30,13 +30,21 @@ public class OnScrollDispatchHelper { * Call from a ScrollView in onScrollChanged, returns true if this onScrollChanged is legit (not a * duplicate) and should be dispatched. */ - public fun onScrollChanged(x: Int, y: Int): Boolean { + public fun onScrollChanged(x: Int, y: Int, duringGesture: Boolean): Boolean { val eventTime = SystemClock.uptimeMillis() val shouldDispatch = eventTime - lastScrollEventTimeMs > MIN_EVENT_SEPARATION_MS || prevX != x || prevY != y - if (eventTime - lastScrollEventTimeMs != 0L) { - xFlingVelocity = (x - prevX).toFloat() / (eventTime - lastScrollEventTimeMs) - yFlingVelocity = (y - prevY).toFloat() / (eventTime - lastScrollEventTimeMs) + if (duringGesture) { + if (eventTime - lastScrollEventTimeMs != 0L) { + xFlingVelocity = (x - prevX).toFloat() / (eventTime - lastScrollEventTimeMs) + yFlingVelocity = (y - prevY).toFloat() / (eventTime - lastScrollEventTimeMs) + } + } else { + // Reset velocity if scroll change was not caused by a gesture, but e.g.: + // - manual scrollTo() call + // - internal scrollTo() call (e.g. in rtl, when list resizes) + xFlingVelocity = 0f + yFlingVelocity = 0f } lastScrollEventTimeMs = eventTime prevX = x diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java index 919777a11fd0..2963b2d6ba5f 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java @@ -488,7 +488,7 @@ protected void onScrollChanged(int x, int y, int oldX, int oldY) { mActivelyScrolling = true; - if (mOnScrollDispatchHelper.onScrollChanged(x, y)) { + if (mOnScrollDispatchHelper.onScrollChanged(x, y, mDragging)) { if (mRemoveClippedSubviews) { updateClippingRect(); } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java index 3d18ba1986b1..11684151532e 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java @@ -414,7 +414,7 @@ protected void onScrollChanged(int x, int y, int oldX, int oldY) { mActivelyScrolling = true; - if (mOnScrollDispatchHelper.onScrollChanged(x, y)) { + if (mOnScrollDispatchHelper.onScrollChanged(x, y, mDragging)) { if (mRemoveClippedSubviews) { updateClippingRect(); }