Skip to content

Commit

Permalink
ScrollView fails when contentInsetAdjustmentBehavior is automatic
Browse files Browse the repository at this point in the history
Summary:
Fix to reactwg/react-native-new-architecture#30
We have already applied this solution to both [pre-Fabric](https://www.internalfb.com/code/fbsource/[1da0f2e3164d6f87e8221e0f0462ae93fdc5cbdc]/xplat/js/react-native-github/React/Views/ScrollView/RCTScrollView.m?lines=361) and [Fabric](https://www.internalfb.com/code/fbsource/[1da0f2e3164d6f87e8221e0f0462ae93fdc5cbdc]/xplat/js/react-native-github/React/Fabric/Mounting/ComponentViews/ScrollView/RCTEnhancedScrollView.mm?lines=36) scroll views. However Fabric can reuse components, and this has to be reapplied at every reuse.
Changelog [iOS][Fixed] - ScrollView's contentInsetAdjustmentBehavior is reset to Never at every reuse to avoid layout artifacts.

Reviewed By: cipolleschi

Differential Revision: D35965080

fbshipit-source-id: 3ac26cf304b608d09ae6c0f05588b664381551f2
  • Loading branch information
Dmitry Rykun authored and facebook-github-bot committed Apr 27, 2022
1 parent dfc24fa commit 28a65f4
Showing 1 changed file with 10 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ @implementation RCTScrollViewComponentView {
// This helps to only update state from `scrollViewDidScroll` in case
// some other part of the system scrolls scroll view.
BOOL _isUserTriggeredScrolling;
BOOL _shouldUpdateContentInsetAdjustmentBehavior;

CGPoint _contentOffsetWhenClipped;
}
Expand All @@ -120,6 +121,7 @@ - (instancetype)initWithFrame:(CGRect)frame
_scrollView.delaysContentTouches = NO;
((RCTEnhancedScrollView *)_scrollView).overridingDelegate = self;
_isUserTriggeredScrolling = NO;
_shouldUpdateContentInsetAdjustmentBehavior = YES;
[self addSubview:_scrollView];

_containerView = [[UIView alloc] initWithFrame:CGRectZero];
Expand Down Expand Up @@ -266,7 +268,8 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &
}
}

if (oldScrollViewProps.contentInsetAdjustmentBehavior != newScrollViewProps.contentInsetAdjustmentBehavior) {
if ((oldScrollViewProps.contentInsetAdjustmentBehavior != newScrollViewProps.contentInsetAdjustmentBehavior) ||
_shouldUpdateContentInsetAdjustmentBehavior) {
auto const contentInsetAdjustmentBehavior = newScrollViewProps.contentInsetAdjustmentBehavior;
if (contentInsetAdjustmentBehavior == ContentInsetAdjustmentBehavior::Never) {
scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
Expand All @@ -277,6 +280,7 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &
} else if (contentInsetAdjustmentBehavior == ContentInsetAdjustmentBehavior::Always) {
scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentAlways;
}
_shouldUpdateContentInsetAdjustmentBehavior = NO;
}

MAP_SCROLL_VIEW_PROP(disableIntervalMomentum);
Expand Down Expand Up @@ -390,6 +394,11 @@ - (void)prepareForRecycle
{
const auto &props = *std::static_pointer_cast<const ScrollViewProps>(_props);
_scrollView.contentOffset = RCTCGPointFromPoint(props.contentOffset);
// We set the default behavior to "never" so that iOS
// doesn't do weird things to UIScrollView insets automatically
// and keeps it as an opt-in behavior.
_scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
_shouldUpdateContentInsetAdjustmentBehavior = YES;
_state.reset();
_isUserTriggeredScrolling = NO;
[super prepareForRecycle];
Expand Down

0 comments on commit 28a65f4

Please sign in to comment.