mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Add scrollEventThrottle prop support in Android
Summary: This diff adds `scrollEventThrottle` prop to Android platform. See [public doc](https://reactnative.dev/docs/scrollview#scrolleventthrottle-ios) for this prop. Currently this is only supported in iOS. The throttling logic is [following](https://github.com/facebook/react-native/blob/main/React/Views/ScrollView/RCTScrollView.m#L650) iOS existing one. Changelog: [Android][Added] - Add scrollEventThrottle prop support in Android Reviewed By: mdvacca Differential Revision: D35735978 fbshipit-source-id: 97b73b4d5fbb93696555917b9252e95fd79ca581
This commit is contained in:
committed by
Facebook GitHub Bot
parent
dd6325bafe
commit
cf55fd587e
@@ -114,4 +114,7 @@ public class ReactFeatureFlags {
|
||||
public static boolean enableSpannableCache = false;
|
||||
|
||||
public static boolean dispatchPointerEvents = false;
|
||||
|
||||
/** Feature Flag to control RN Android scrollEventThrottle prop. */
|
||||
public static boolean enableScrollEventThrottle = false;
|
||||
}
|
||||
|
||||
+25
-1
@@ -43,6 +43,7 @@ import com.facebook.react.uimanager.ReactOverflowViewWithInset;
|
||||
import com.facebook.react.uimanager.ViewProps;
|
||||
import com.facebook.react.uimanager.events.NativeGestureUtil;
|
||||
import com.facebook.react.views.scroll.ReactScrollViewHelper.HasFlingAnimator;
|
||||
import com.facebook.react.views.scroll.ReactScrollViewHelper.HasScrollEventThrottle;
|
||||
import com.facebook.react.views.scroll.ReactScrollViewHelper.HasScrollState;
|
||||
import com.facebook.react.views.scroll.ReactScrollViewHelper.ReactScrollViewScrollState;
|
||||
import com.facebook.react.views.view.ReactViewBackgroundManager;
|
||||
@@ -56,7 +57,8 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
||||
FabricViewStateManager.HasFabricViewStateManager,
|
||||
ReactOverflowViewWithInset,
|
||||
HasScrollState,
|
||||
HasFlingAnimator {
|
||||
HasFlingAnimator,
|
||||
HasScrollEventThrottle {
|
||||
|
||||
private static boolean DEBUG_MODE = false && ReactBuildConfig.DEBUG;
|
||||
private static String TAG = ReactHorizontalScrollView.class.getSimpleName();
|
||||
@@ -103,6 +105,8 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
||||
private final ReactScrollViewScrollState mReactScrollViewScrollState;
|
||||
private final ValueAnimator DEFAULT_FLING_ANIMATOR = ObjectAnimator.ofInt(this, "scrollX", 0, 0);
|
||||
private PointerEvents mPointerEvents = PointerEvents.AUTO;
|
||||
private long mLastScrollDispatchTime = 0;
|
||||
private int mScrollEventThrottle = 0;
|
||||
|
||||
private final Rect mTempRect = new Rect();
|
||||
|
||||
@@ -1272,4 +1276,24 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
||||
public PointerEvents getPointerEvents() {
|
||||
return mPointerEvents;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScrollEventThrottle(int scrollEventThrottle) {
|
||||
mScrollEventThrottle = scrollEventThrottle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getScrollEventThrottle() {
|
||||
return mScrollEventThrottle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLastScrollDispatchTime(long lastScrollDispatchTime) {
|
||||
mLastScrollDispatchTime = lastScrollDispatchTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastScrollDispatchTime() {
|
||||
return mLastScrollDispatchTime;
|
||||
}
|
||||
}
|
||||
|
||||
+5
@@ -325,4 +325,9 @@ public class ReactHorizontalScrollViewManager extends ViewGroupManager<ReactHori
|
||||
public void setPointerEvents(ReactHorizontalScrollView view, @Nullable String pointerEventsStr) {
|
||||
view.setPointerEvents(PointerEvents.parsePointerEvents(pointerEventsStr));
|
||||
}
|
||||
|
||||
@ReactProp(name = "scrollEventThrottle")
|
||||
public void setScrollEventThrottle(ReactHorizontalScrollView view, int scrollEventThrottle) {
|
||||
view.setScrollEventThrottle(scrollEventThrottle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ import com.facebook.react.uimanager.ReactOverflowViewWithInset;
|
||||
import com.facebook.react.uimanager.ViewProps;
|
||||
import com.facebook.react.uimanager.events.NativeGestureUtil;
|
||||
import com.facebook.react.views.scroll.ReactScrollViewHelper.HasFlingAnimator;
|
||||
import com.facebook.react.views.scroll.ReactScrollViewHelper.HasScrollEventThrottle;
|
||||
import com.facebook.react.views.scroll.ReactScrollViewHelper.HasScrollState;
|
||||
import com.facebook.react.views.scroll.ReactScrollViewHelper.ReactScrollViewScrollState;
|
||||
import com.facebook.react.views.view.ReactViewBackgroundManager;
|
||||
@@ -62,7 +63,8 @@ public class ReactScrollView extends ScrollView
|
||||
FabricViewStateManager.HasFabricViewStateManager,
|
||||
ReactOverflowViewWithInset,
|
||||
HasScrollState,
|
||||
HasFlingAnimator {
|
||||
HasFlingAnimator,
|
||||
HasScrollEventThrottle {
|
||||
|
||||
private static @Nullable Field sScrollerField;
|
||||
private static boolean sTriedToGetScrollerField = false;
|
||||
@@ -104,6 +106,8 @@ public class ReactScrollView extends ScrollView
|
||||
new ReactScrollViewScrollState(ViewCompat.LAYOUT_DIRECTION_LTR);
|
||||
private final ValueAnimator DEFAULT_FLING_ANIMATOR = ObjectAnimator.ofInt(this, "scrollY", 0, 0);
|
||||
private PointerEvents mPointerEvents = PointerEvents.AUTO;
|
||||
private long mLastScrollDispatchTime = 0;
|
||||
private int mScrollEventThrottle = 0;
|
||||
|
||||
public ReactScrollView(Context context) {
|
||||
this(context, null);
|
||||
@@ -1168,4 +1172,24 @@ public class ReactScrollView extends ScrollView
|
||||
public PointerEvents getPointerEvents() {
|
||||
return mPointerEvents;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScrollEventThrottle(int scrollEventThrottle) {
|
||||
mScrollEventThrottle = scrollEventThrottle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getScrollEventThrottle() {
|
||||
return mScrollEventThrottle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLastScrollDispatchTime(long lastScrollDispatchTime) {
|
||||
mLastScrollDispatchTime = lastScrollDispatchTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastScrollDispatchTime() {
|
||||
return mLastScrollDispatchTime;
|
||||
}
|
||||
}
|
||||
|
||||
+45
-11
@@ -22,6 +22,7 @@ import com.facebook.react.bridge.ReactContext;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
import com.facebook.react.bridge.WritableNativeMap;
|
||||
import com.facebook.react.common.build.ReactBuildConfig;
|
||||
import com.facebook.react.config.ReactFeatureFlags;
|
||||
import com.facebook.react.uimanager.FabricViewStateManager;
|
||||
import com.facebook.react.uimanager.PixelUtil;
|
||||
import com.facebook.react.uimanager.UIManagerHelper;
|
||||
@@ -68,34 +69,49 @@ public class ReactScrollViewHelper {
|
||||
private static boolean mSmoothScrollDurationInitialized = false;
|
||||
|
||||
/** Shared by {@link ReactScrollView} and {@link ReactHorizontalScrollView}. */
|
||||
public static void emitScrollEvent(ViewGroup scrollView, float xVelocity, float yVelocity) {
|
||||
public static <T extends ViewGroup & HasScrollEventThrottle> void emitScrollEvent(
|
||||
T scrollView, float xVelocity, float yVelocity) {
|
||||
emitScrollEvent(scrollView, ScrollEventType.SCROLL, xVelocity, yVelocity);
|
||||
}
|
||||
|
||||
public static void emitScrollBeginDragEvent(ViewGroup scrollView) {
|
||||
public static <T extends ViewGroup & HasScrollEventThrottle> void emitScrollBeginDragEvent(
|
||||
T scrollView) {
|
||||
emitScrollEvent(scrollView, ScrollEventType.BEGIN_DRAG);
|
||||
}
|
||||
|
||||
public static void emitScrollEndDragEvent(
|
||||
ViewGroup scrollView, float xVelocity, float yVelocity) {
|
||||
public static <T extends ViewGroup & HasScrollEventThrottle> void emitScrollEndDragEvent(
|
||||
T scrollView, float xVelocity, float yVelocity) {
|
||||
emitScrollEvent(scrollView, ScrollEventType.END_DRAG, xVelocity, yVelocity);
|
||||
}
|
||||
|
||||
public static void emitScrollMomentumBeginEvent(
|
||||
ViewGroup scrollView, int xVelocity, int yVelocity) {
|
||||
public static <T extends ViewGroup & HasScrollEventThrottle> void emitScrollMomentumBeginEvent(
|
||||
T scrollView, int xVelocity, int yVelocity) {
|
||||
emitScrollEvent(scrollView, ScrollEventType.MOMENTUM_BEGIN, xVelocity, yVelocity);
|
||||
}
|
||||
|
||||
public static void emitScrollMomentumEndEvent(ViewGroup scrollView) {
|
||||
public static <T extends ViewGroup & HasScrollEventThrottle> void emitScrollMomentumEndEvent(
|
||||
T scrollView) {
|
||||
emitScrollEvent(scrollView, ScrollEventType.MOMENTUM_END);
|
||||
}
|
||||
|
||||
private static void emitScrollEvent(ViewGroup scrollView, ScrollEventType scrollEventType) {
|
||||
private static <T extends ViewGroup & HasScrollEventThrottle> void emitScrollEvent(
|
||||
T scrollView, ScrollEventType scrollEventType) {
|
||||
emitScrollEvent(scrollView, scrollEventType, 0, 0);
|
||||
}
|
||||
|
||||
private static void emitScrollEvent(
|
||||
ViewGroup scrollView, ScrollEventType scrollEventType, float xVelocity, float yVelocity) {
|
||||
private static <T extends ViewGroup & HasScrollEventThrottle> void emitScrollEvent(
|
||||
T scrollView, ScrollEventType scrollEventType, float xVelocity, float yVelocity) {
|
||||
long now = System.currentTimeMillis();
|
||||
// Throttle the scroll event if scrollEventThrottle is set to be equal or more than 17 ms.
|
||||
// We limit the delta to 17ms so that small throttles intended to enable 60fps updates will not
|
||||
// inadvertently filter out any scroll events.
|
||||
if (ReactFeatureFlags.enableScrollEventThrottle
|
||||
&& scrollView.getScrollEventThrottle()
|
||||
>= Math.max(17, now - scrollView.getLastScrollDispatchTime())) {
|
||||
// Scroll events are throttled.
|
||||
return;
|
||||
}
|
||||
|
||||
View contentView = scrollView.getChildAt(0);
|
||||
|
||||
if (contentView == null) {
|
||||
@@ -129,6 +145,7 @@ public class ReactScrollViewHelper {
|
||||
contentView.getHeight(),
|
||||
scrollView.getWidth(),
|
||||
scrollView.getHeight()));
|
||||
scrollView.setLastScrollDispatchTime(now);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -469,7 +486,7 @@ public class ReactScrollViewHelper {
|
||||
public static <
|
||||
T extends
|
||||
ViewGroup & FabricViewStateManager.HasFabricViewStateManager & HasScrollState
|
||||
& HasFlingAnimator>
|
||||
& HasFlingAnimator & HasScrollEventThrottle>
|
||||
void updateStateOnScrollChanged(
|
||||
final T scrollView, final float xVelocity, final float yVelocity) {
|
||||
// Race an UpdateState with every onScroll. This makes it more likely that, in Fabric,
|
||||
@@ -579,4 +596,21 @@ public class ReactScrollViewHelper {
|
||||
/** Get the fling distance with current velocity for prediction */
|
||||
int getFlingExtrapolatedDistance(int velocity);
|
||||
}
|
||||
|
||||
public interface HasScrollEventThrottle {
|
||||
/**
|
||||
* Set the scroll event throttle in ms. This number is used to throttle the scroll events. The
|
||||
* default value is zero, which means the scroll events are sent with no throttle.
|
||||
*/
|
||||
void setScrollEventThrottle(int scrollEventThrottle);
|
||||
|
||||
/** Get the scroll event throttle in ms. */
|
||||
int getScrollEventThrottle();
|
||||
|
||||
/** Set the scroll view's last dispatch time for throttling */
|
||||
void setLastScrollDispatchTime(long lastScrollDispatchTime);
|
||||
|
||||
/** Get the scroll view dispatch time for throttling */
|
||||
long getLastScrollDispatchTime();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -367,4 +367,9 @@ public class ReactScrollViewManager extends ViewGroupManager<ReactScrollView>
|
||||
public void setPointerEvents(ReactScrollView view, @Nullable String pointerEventsStr) {
|
||||
view.setPointerEvents(PointerEvents.parsePointerEvents(pointerEventsStr));
|
||||
}
|
||||
|
||||
@ReactProp(name = "scrollEventThrottle")
|
||||
public void setScrollEventThrottle(ReactScrollView view, int scrollEventThrottle) {
|
||||
view.setScrollEventThrottle(scrollEventThrottle);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user