|
22 | 22 | import com.facebook.react.bridge.WritableMap;
|
23 | 23 | import com.facebook.react.bridge.WritableNativeMap;
|
24 | 24 | import com.facebook.react.common.build.ReactBuildConfig;
|
| 25 | +import com.facebook.react.config.ReactFeatureFlags; |
25 | 26 | import com.facebook.react.uimanager.FabricViewStateManager;
|
26 | 27 | import com.facebook.react.uimanager.PixelUtil;
|
27 | 28 | import com.facebook.react.uimanager.UIManagerHelper;
|
@@ -68,34 +69,49 @@ void onScroll(
|
68 | 69 | private static boolean mSmoothScrollDurationInitialized = false;
|
69 | 70 |
|
70 | 71 | /** Shared by {@link ReactScrollView} and {@link ReactHorizontalScrollView}. */
|
71 |
| - public static void emitScrollEvent(ViewGroup scrollView, float xVelocity, float yVelocity) { |
| 72 | + public static <T extends ViewGroup & HasScrollEventThrottle> void emitScrollEvent( |
| 73 | + T scrollView, float xVelocity, float yVelocity) { |
72 | 74 | emitScrollEvent(scrollView, ScrollEventType.SCROLL, xVelocity, yVelocity);
|
73 | 75 | }
|
74 | 76 |
|
75 |
| - public static void emitScrollBeginDragEvent(ViewGroup scrollView) { |
| 77 | + public static <T extends ViewGroup & HasScrollEventThrottle> void emitScrollBeginDragEvent( |
| 78 | + T scrollView) { |
76 | 79 | emitScrollEvent(scrollView, ScrollEventType.BEGIN_DRAG);
|
77 | 80 | }
|
78 | 81 |
|
79 |
| - public static void emitScrollEndDragEvent( |
80 |
| - ViewGroup scrollView, float xVelocity, float yVelocity) { |
| 82 | + public static <T extends ViewGroup & HasScrollEventThrottle> void emitScrollEndDragEvent( |
| 83 | + T scrollView, float xVelocity, float yVelocity) { |
81 | 84 | emitScrollEvent(scrollView, ScrollEventType.END_DRAG, xVelocity, yVelocity);
|
82 | 85 | }
|
83 | 86 |
|
84 |
| - public static void emitScrollMomentumBeginEvent( |
85 |
| - ViewGroup scrollView, int xVelocity, int yVelocity) { |
| 87 | + public static <T extends ViewGroup & HasScrollEventThrottle> void emitScrollMomentumBeginEvent( |
| 88 | + T scrollView, int xVelocity, int yVelocity) { |
86 | 89 | emitScrollEvent(scrollView, ScrollEventType.MOMENTUM_BEGIN, xVelocity, yVelocity);
|
87 | 90 | }
|
88 | 91 |
|
89 |
| - public static void emitScrollMomentumEndEvent(ViewGroup scrollView) { |
| 92 | + public static <T extends ViewGroup & HasScrollEventThrottle> void emitScrollMomentumEndEvent( |
| 93 | + T scrollView) { |
90 | 94 | emitScrollEvent(scrollView, ScrollEventType.MOMENTUM_END);
|
91 | 95 | }
|
92 | 96 |
|
93 |
| - private static void emitScrollEvent(ViewGroup scrollView, ScrollEventType scrollEventType) { |
| 97 | + private static <T extends ViewGroup & HasScrollEventThrottle> void emitScrollEvent( |
| 98 | + T scrollView, ScrollEventType scrollEventType) { |
94 | 99 | emitScrollEvent(scrollView, scrollEventType, 0, 0);
|
95 | 100 | }
|
96 | 101 |
|
97 |
| - private static void emitScrollEvent( |
98 |
| - ViewGroup scrollView, ScrollEventType scrollEventType, float xVelocity, float yVelocity) { |
| 102 | + private static <T extends ViewGroup & HasScrollEventThrottle> void emitScrollEvent( |
| 103 | + T scrollView, ScrollEventType scrollEventType, float xVelocity, float yVelocity) { |
| 104 | + long now = System.currentTimeMillis(); |
| 105 | + // Throttle the scroll event if scrollEventThrottle is set to be equal or more than 17 ms. |
| 106 | + // We limit the delta to 17ms so that small throttles intended to enable 60fps updates will not |
| 107 | + // inadvertently filter out any scroll events. |
| 108 | + if (ReactFeatureFlags.enableScrollEventThrottle |
| 109 | + && scrollView.getScrollEventThrottle() |
| 110 | + >= Math.max(17, now - scrollView.getLastScrollDispatchTime())) { |
| 111 | + // Scroll events are throttled. |
| 112 | + return; |
| 113 | + } |
| 114 | + |
99 | 115 | View contentView = scrollView.getChildAt(0);
|
100 | 116 |
|
101 | 117 | if (contentView == null) {
|
@@ -129,6 +145,7 @@ private static void emitScrollEvent(
|
129 | 145 | contentView.getHeight(),
|
130 | 146 | scrollView.getWidth(),
|
131 | 147 | scrollView.getHeight()));
|
| 148 | + scrollView.setLastScrollDispatchTime(now); |
132 | 149 | }
|
133 | 150 | }
|
134 | 151 |
|
@@ -469,7 +486,7 @@ public WritableMap getStateUpdate() {
|
469 | 486 | public static <
|
470 | 487 | T extends
|
471 | 488 | ViewGroup & FabricViewStateManager.HasFabricViewStateManager & HasScrollState
|
472 |
| - & HasFlingAnimator> |
| 489 | + & HasFlingAnimator & HasScrollEventThrottle> |
473 | 490 | void updateStateOnScrollChanged(
|
474 | 491 | final T scrollView, final float xVelocity, final float yVelocity) {
|
475 | 492 | // Race an UpdateState with every onScroll. This makes it more likely that, in Fabric,
|
@@ -579,4 +596,21 @@ public interface HasFlingAnimator {
|
579 | 596 | /** Get the fling distance with current velocity for prediction */
|
580 | 597 | int getFlingExtrapolatedDistance(int velocity);
|
581 | 598 | }
|
| 599 | + |
| 600 | + public interface HasScrollEventThrottle { |
| 601 | + /** |
| 602 | + * Set the scroll event throttle in ms. This number is used to throttle the scroll events. The |
| 603 | + * default value is zero, which means the scroll events are sent with no throttle. |
| 604 | + */ |
| 605 | + void setScrollEventThrottle(int scrollEventThrottle); |
| 606 | + |
| 607 | + /** Get the scroll event throttle in ms. */ |
| 608 | + int getScrollEventThrottle(); |
| 609 | + |
| 610 | + /** Set the scroll view's last dispatch time for throttling */ |
| 611 | + void setLastScrollDispatchTime(long lastScrollDispatchTime); |
| 612 | + |
| 613 | + /** Get the scroll view dispatch time for throttling */ |
| 614 | + long getLastScrollDispatchTime(); |
| 615 | + } |
582 | 616 | }
|
0 commit comments