Fix scrollView state contentOffset not being in sync with scrollView contentOffset

Summary:
Changelog: [Internal]

# Problem
`scrollView.state.contentOffset` was not in sync with actual `contentOffset` in case `contentOffset` is changed programatically.

# Solution
Add a flag `_isUserTriggeredScrolling` that indicates whether the current scroll is triggered by user or not. In case it isn't, update state.

Reviewed By: shergin

Differential Revision: D20098161

fbshipit-source-id: 021d916e7a45a24095a47bb8f84d1102226b672a
This commit is contained in:
Samuel Susla
2020-03-10 12:44:17 -07:00
committed by Facebook Github Bot
parent 507379f6fa
commit cd0e4ecd7b
@@ -48,6 +48,11 @@ static void RCTSendPaperScrollEvent_DEPRECATED(UIScrollView *scrollView, NSInteg
CGSize _contentSize;
NSTimeInterval _lastScrollEventDispatchTime;
NSTimeInterval _scrollEventThrottle;
// Flag indicating whether the scrolling that is currently happening
// is triggered by user or not.
// This helps to only update state from `scrollViewDidScroll` in case
// some other part of the system scrolls scroll view.
BOOL _isUserTriggeredScrolling;
}
+ (RCTScrollViewComponentView *_Nullable)findScrollViewComponentViewForView:(UIView *)view
@@ -67,6 +72,7 @@ static void RCTSendPaperScrollEvent_DEPRECATED(UIScrollView *scrollView, NSInteg
_scrollView = [[RCTEnhancedScrollView alloc] initWithFrame:self.bounds];
_scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
_scrollView.delaysContentTouches = NO;
_isUserTriggeredScrolling = NO;
[self addSubview:_scrollView];
_containerView = [[UIView alloc] initWithFrame:CGRectZero];
@@ -204,8 +210,10 @@ static void RCTSendPaperScrollEvent_DEPRECATED(UIScrollView *scrollView, NSInteg
- (void)_updateStateWithContentOffset
{
if (!_state) {
return;
}
auto contentOffset = RCTPointFromCGPoint(_scrollView.contentOffset);
_state->updateState([contentOffset](ScrollViewShadowNode::ConcreteState::Data const &data) {
auto newData = data;
newData.contentOffset = contentOffset;
@@ -217,6 +225,7 @@ static void RCTSendPaperScrollEvent_DEPRECATED(UIScrollView *scrollView, NSInteg
{
_scrollView.contentOffset = CGPointZero;
_state.reset();
_isUserTriggeredScrolling = NO;
[super prepareForRecycle];
}
@@ -224,6 +233,9 @@ static void RCTSendPaperScrollEvent_DEPRECATED(UIScrollView *scrollView, NSInteg
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (!_isUserTriggeredScrolling) {
[self _updateStateWithContentOffset];
}
if (!_eventEmitter) {
return;
}
@@ -243,6 +255,18 @@ static void RCTSendPaperScrollEvent_DEPRECATED(UIScrollView *scrollView, NSInteg
[self scrollViewDidScroll:scrollView];
}
- (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView
{
_isUserTriggeredScrolling = YES;
return YES;
}
- (void)scrollViewDidScrollToTop:(UIScrollView *)scrollView
{
_isUserTriggeredScrolling = NO;
[self _updateStateWithContentOffset];
}
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
[self _forceDispatchNextScrollEvent];
@@ -252,6 +276,7 @@ static void RCTSendPaperScrollEvent_DEPRECATED(UIScrollView *scrollView, NSInteg
}
std::static_pointer_cast<ScrollViewEventEmitter const>(_eventEmitter)->onScrollBeginDrag([self _scrollViewMetrics]);
_isUserTriggeredScrolling = YES;
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
@@ -288,6 +313,7 @@ static void RCTSendPaperScrollEvent_DEPRECATED(UIScrollView *scrollView, NSInteg
std::static_pointer_cast<ScrollViewEventEmitter const>(_eventEmitter)->onMomentumScrollEnd([self _scrollViewMetrics]);
[self _updateStateWithContentOffset];
_isUserTriggeredScrolling = NO;
}
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView