mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
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:
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
|
||||
|
||||
Reference in New Issue
Block a user