diff --git a/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm b/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm index 8c95cdbc0b9e18..ae41b9cb8dfd2b 100644 --- a/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm @@ -25,6 +25,12 @@ using namespace facebook::react; +struct PendingOffset { + bool isPending; + CGPoint offset; + CGPoint lastOffset; +}; + static CGFloat const kClippingLeeway = 44.0; static UIScrollViewKeyboardDismissMode RCTUIKeyboardDismissModeFromProps(ScrollViewProps const &props) @@ -99,6 +105,8 @@ @implementation RCTScrollViewComponentView { BOOL _shouldUpdateContentInsetAdjustmentBehavior; CGPoint _contentOffsetWhenClipped; + + PendingOffset _pendingOffset; } + (RCTScrollViewComponentView *_Nullable)findScrollViewComponentViewForView:(UIView *)view @@ -173,6 +181,12 @@ - (void)updateLayoutMetrics:(const LayoutMetrics &)layoutMetrics _containerView.transform = transform; _scrollView.transform = transform; } + + // If there is a pending offset, apply it + if (_pendingOffset.isPending) { + [self scrollTo:_pendingOffset.offset.x y:_pendingOffset.offset.y animated:false]; + _pendingOffset.isPending = false; + } } - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps @@ -421,6 +435,13 @@ - (void)scrollViewDidScroll:(UIScrollView *)scrollView [self _updateStateWithContentOffset]; } + // If the view is hidden, then set as pending offset. Apply it later on + // updateLayoutMetrics. + if (_scrollView.window == nil && !_pendingOffset.isPending) { + _pendingOffset.offset = _pendingOffset.lastOffset; + _pendingOffset.isPending = true; + } + NSTimeInterval now = CACurrentMediaTime(); if ((_lastScrollEventDispatchTime == 0) || (now - _lastScrollEventDispatchTime > _scrollEventThrottle)) { _lastScrollEventDispatchTime = now; @@ -431,6 +452,8 @@ - (void)scrollViewDidScroll:(UIScrollView *)scrollView RCTSendScrollEventForNativeAnimations_DEPRECATED(scrollView, self.tag); } + _pendingOffset.lastOffset = _scrollView.contentOffset; + [self _remountChildrenIfNeeded]; }