From 1d837d2039b169b20a413922577e568cab55b43e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hanno=20J=2E=20G=C3=B6decke?= Date: Tue, 9 Dec 2025 17:21:12 +0100 Subject: [PATCH] scrollview: add option to tag event while drawing --- .../facebook/react/shell/MainReactPackage.kt | 6 ++-- .../facebook/react/uimanager/events/Event.kt | 3 ++ .../react/views/scroll/ReactScrollView.java | 35 +++++++++++-------- .../views/scroll/ReactScrollViewHelper.kt | 14 +++++--- 4 files changed, 35 insertions(+), 23 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.kt index 2089157dc49411..bca6cc178dac52 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.kt @@ -139,7 +139,7 @@ constructor(private val config: MainPackageConfig? = null) : ReactHorizontalScrollViewManager(), ReactHorizontalScrollContainerViewManager(), ReactProgressBarViewManager(), - ReactScrollViewManager(), + // ReactScrollViewManager(), ReactSwitchManager(), ReactSafeAreaViewManager(), SwipeRefreshLayoutManager(), @@ -172,8 +172,8 @@ constructor(private val config: MainPackageConfig? = null) : ModuleSpec.viewManagerSpec { ReactProgressBarViewManager() }, ReactSafeAreaViewManager.REACT_CLASS to ModuleSpec.viewManagerSpec { ReactSafeAreaViewManager() }, - ReactScrollViewManager.REACT_CLASS to - ModuleSpec.viewManagerSpec { ReactScrollViewManager() }, + // ReactScrollViewManager.REACT_CLASS to + // ModuleSpec.viewManagerSpec { ReactScrollViewManager() }, ReactSwitchManager.REACT_CLASS to ModuleSpec.viewManagerSpec { ReactSwitchManager() }, SwipeRefreshLayoutManager.REACT_CLASS to ModuleSpec.viewManagerSpec { SwipeRefreshLayoutManager() }, diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/Event.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/Event.kt index d90bcdc98afe0f..20743cd076a0a3 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/Event.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/Event.kt @@ -40,6 +40,9 @@ public abstract class Event> { public var viewTag: Int = 0 private set + /** @return whether this event is dispatched during a drawing pass */ + public var isDrawing: Boolean = false + /** * @return the time at which the event happened in the [android.os.SystemClock.uptimeMillis] base. */ 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 7b12e496bd856d..25a0ed2c1f0408 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 @@ -463,24 +463,29 @@ private void scrollToChild(View child) { @Override protected void onScrollChanged(int x, int y, int oldX, int oldY) { - Systrace.beginSection(Systrace.TRACE_TAG_REACT, "ReactScrollView.onScrollChanged"); - try { - super.onScrollChanged(x, y, oldX, oldY); + onScrollChanged(x, y, oldX, oldY, false); + } - mActivelyScrolling = true; + protected void onScrollChanged(int x, int y, int oldX, int oldY, boolean isDrawing) { + Systrace.beginSection(Systrace.TRACE_TAG_REACT, "ReactScrollView.onScrollChanged"); + try { + super.onScrollChanged(x, y, oldX, oldY); - if (mOnScrollDispatchHelper.onScrollChanged(x, y)) { - if (mRemoveClippedSubviews) { - updateClippingRect(); - } - ReactScrollViewHelper.updateStateOnScrollChanged( - this, - mOnScrollDispatchHelper.getXFlingVelocity(), - mOnScrollDispatchHelper.getYFlingVelocity()); + mActivelyScrolling = true; + + if (mOnScrollDispatchHelper.onScrollChanged(x, y)) { + if (mRemoveClippedSubviews) { + updateClippingRect(); + } + ReactScrollViewHelper.updateStateOnScrollChanged( + this, + mOnScrollDispatchHelper.getXFlingVelocity(), + mOnScrollDispatchHelper.getYFlingVelocity(), + isDrawing); + } + } finally { + Systrace.endSection(Systrace.TRACE_TAG_REACT); } - } finally { - Systrace.endSection(Systrace.TRACE_TAG_REACT); - } } @Override diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewHelper.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewHelper.kt index 55e4d53fb94cb1..f2360e0e9c62fc 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewHelper.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewHelper.kt @@ -65,10 +65,10 @@ public object ReactScrollViewHelper { /** Shared by [ReactScrollView] and [ReactHorizontalScrollView]. */ @JvmStatic - public fun emitScrollEvent(scrollView: T, xVelocity: Float, yVelocity: Float) where + public fun emitScrollEvent(scrollView: T, xVelocity: Float, yVelocity: Float, isDrawing: Boolean = false) where T : HasScrollEventThrottle?, T : ViewGroup { - emitScrollEvent(scrollView, ScrollEventType.SCROLL, xVelocity, yVelocity) + emitScrollEvent(scrollView, ScrollEventType.SCROLL, xVelocity, yVelocity, isDrawing) } @JvmStatic @@ -111,6 +111,7 @@ public object ReactScrollViewHelper { scrollEventType: ScrollEventType, xVelocity: Float, yVelocity: Float, + isDrawing: Boolean = false ) where T : HasScrollEventThrottle?, T : ViewGroup { val now = System.currentTimeMillis() // Throttle the scroll event if scrollEventThrottle is set to be equal or more than 17 ms. @@ -146,7 +147,9 @@ public object ReactScrollViewHelper { contentView.width, contentView.height, scrollView.width, - scrollView.height)) + scrollView.height).also { + it.isDrawing = isDrawing + }) if (scrollEventType == ScrollEventType.SCROLL) { scrollView.lastScrollDispatchTime = now } @@ -368,7 +371,8 @@ public object ReactScrollViewHelper { public fun updateStateOnScrollChanged( scrollView: T, xVelocity: Float, - yVelocity: Float + yVelocity: Float, + isDrawing: Boolean = false ) where T : HasFlingAnimator?, T : HasScrollEventThrottle?, @@ -380,7 +384,7 @@ public object ReactScrollViewHelper { // "more correct" scroll position. It will frequently be /incorrect/ but this decreases // the error as much as possible. updateFabricScrollState(scrollView, scrollView.scrollX, scrollView.scrollY) - emitScrollEvent(scrollView, xVelocity, yVelocity) + emitScrollEvent(scrollView, xVelocity, yVelocity, isDrawing) } public fun registerFlingAnimator(scrollView: T) where