From 6ecd9a43f16e76771e2f970972bcd067aa570cf7 Mon Sep 17 00:00:00 2001 From: Jakub Piasecki Date: Wed, 12 Mar 2025 03:50:07 -0700 Subject: [PATCH] Fix touch events not being dispatched to ScrollView's children when they overflow content container (#49855) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/49855 Changelog: [IOS][FIXED] - Fixed touch events not being dispatched to ScrollView's children when they overflow the content container Closes https://github.com/facebook/react-native/issues/47740. Changes the ScrollView's container view to be `RCTViewComponentView` instead of `UIView` and sets custom layout metrics to it in a way that it will propagate touch events to all children, even if they overflow its bounds. Reviewed By: sammy-SC Differential Revision: D70619894 fbshipit-source-id: 348a1a369489d5208d6037c8d76b223c4ab2d5f7 --- .../ScrollView/RCTScrollViewComponentView.mm | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm index d029337fb0d..9b4e6aad2ec 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm @@ -89,6 +89,7 @@ RCTSendScrollEventForNativeAnimations_DEPRECATED(UIScrollView *scrollView, NSInt @implementation RCTScrollViewComponentView { ScrollViewShadowNode::ConcreteState::Shared _state; + LayoutMetrics _lastContentContainerLayoutMetrics; CGSize _contentSize; NSTimeInterval _lastScrollEventDispatchTime; NSTimeInterval _scrollEventThrottle; @@ -132,7 +133,7 @@ RCTSendScrollEventForNativeAnimations_DEPRECATED(UIScrollView *scrollView, NSInt _automaticallyAdjustKeyboardInsets = NO; [self addSubview:_scrollView]; - _containerView = [[UIView alloc] initWithFrame:CGRectZero]; + _containerView = [[RCTViewComponentView alloc] initWithFrame:CGRectZero]; [_scrollView addSubview:_containerView]; [self.scrollViewDelegateSplitter addDelegate:self]; @@ -468,7 +469,11 @@ static inline UIViewAnimationOptions animationOptionsWithCurve(UIViewAnimationCu } _contentSize = contentSize; - _containerView.frame = CGRect{RCTCGPointFromPoint(data.contentBoundingRect.origin), contentSize}; + LayoutMetrics newContentContainerLayoutMetrics = LayoutMetrics{ + .frame = {.origin = data.contentBoundingRect.origin, .size = data.getContentSize()}, .overflowInset = {.top = 1}}; + [_containerView updateLayoutMetrics:newContentContainerLayoutMetrics + oldLayoutMetrics:_lastContentContainerLayoutMetrics]; + _lastContentContainerLayoutMetrics = newContentContainerLayoutMetrics; [self _preserveContentOffsetIfNeededWithBlock:^{ self->_scrollView.contentSize = contentSize;