Skip to content

Commit 39776a8

Browse files
sahrensgrabbou
authored andcommitted
don't throttle below 16ms
Summary: For some reason the scroll events are sometimes generated with highly irregular spacing, some coming less than a millisecond apart. For interactions that must track scrolling exactly, this can cause them to glitch. With a scroll throttle of less than 17 ms, the intention is clear that the UI should be updated in sync with the scroll view so we shouldn't drop any events. Reviewed By: PeteTheHeat Differential Revision: D15068841 fbshipit-source-id: 730e7cb29cc3ddae66f37cf7392e02e0cc9d7844
1 parent 379874d commit 39776a8

File tree

3 files changed

+18
-8
lines changed

3 files changed

+18
-8
lines changed

Libraries/Animated/src/components/AnimatedScrollView.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,6 @@ const ScrollView = require('ScrollView');
1414

1515
const createAnimatedComponent = require('createAnimatedComponent');
1616

17-
module.exports = createAnimatedComponent(ScrollView);
17+
module.exports = createAnimatedComponent(ScrollView, {
18+
scrollEventThrottle: 0.0001,
19+
});

Libraries/Components/ScrollView/ScrollView.js

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -195,11 +195,16 @@ type IOSProps = $ReadOnly<{|
195195
* (as a time interval in ms). A lower number yields better accuracy for code
196196
* that is tracking the scroll position, but can lead to scroll performance
197197
* problems due to the volume of information being send over the bridge.
198-
* You will not notice a difference between values set between 1-16 as the
199-
* JS run loop is synced to the screen refresh rate. If you do not need precise
200-
* scroll position tracking, set this value higher to limit the information
201-
* being sent across the bridge. The default value is zero, which results in
202-
* the scroll event being sent only once each time the view is scrolled.
198+
*
199+
* Values between 0 and 17ms indicate 60fps updates are needed and throttling
200+
* will be disabled.
201+
*
202+
* If you do not need precise scroll position tracking, set this value higher
203+
* to limit the information being sent across the bridge.
204+
*
205+
* The default value is zero, which results in the scroll event being sent only
206+
* once each time the view is scrolled.
207+
*
203208
* @platform ios
204209
*/
205210
scrollEventThrottle?: ?number,

React/Views/ScrollView/RCTScrollView.m

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -676,16 +676,19 @@ - (void)removeScrollListener:(NSObject<UIScrollViewDelegate> *)scrollListener
676676

677677
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
678678
{
679-
[self updateClippedSubviews];
680679
NSTimeInterval now = CACurrentMediaTime();
680+
[self updateClippedSubviews];
681681
/**
682682
* TODO: this logic looks wrong, and it may be because it is. Currently, if _scrollEventThrottle
683683
* is set to zero (the default), the "didScroll" event is only sent once per scroll, instead of repeatedly
684684
* while scrolling as expected. However, if you "fix" that bug, ScrollView will generate repeated
685685
* warnings, and behave strangely (ListView works fine however), so don't fix it unless you fix that too!
686+
*
687+
* We limit the delta to 17ms so that small throttles intended to enable 60fps updates will not
688+
* inadvertantly filter out any scroll events.
686689
*/
687690
if (_allowNextScrollNoMatterWhat ||
688-
(_scrollEventThrottle > 0 && _scrollEventThrottle < (now - _lastScrollDispatchTime))) {
691+
(_scrollEventThrottle > 0 && _scrollEventThrottle < MAX(17, now - _lastScrollDispatchTime))) {
689692

690693
if (_DEPRECATED_sendUpdatedChildFrames) {
691694
// Calculate changed frames

0 commit comments

Comments
 (0)