Skip to content

Commit b8e4637

Browse files
committed
Fix keyboard inset state across ScrollView recycling
1 parent 88feed5 commit b8e4637

2 files changed

Lines changed: 65 additions & 3 deletions

File tree

packages/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -360,9 +360,7 @@ - (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared &
360360
MAP_SCROLL_VIEW_PROP(showsHorizontalScrollIndicator);
361361
MAP_SCROLL_VIEW_PROP(showsVerticalScrollIndicator);
362362

363-
if (oldScrollViewProps.automaticallyAdjustKeyboardInsets != newScrollViewProps.automaticallyAdjustKeyboardInsets) {
364-
_automaticallyAdjustKeyboardInsets = newScrollViewProps.automaticallyAdjustKeyboardInsets;
365-
}
363+
_automaticallyAdjustKeyboardInsets = newScrollViewProps.automaticallyAdjustKeyboardInsets;
366364

367365
if (oldScrollViewProps.scrollIndicatorInsets != newScrollViewProps.scrollIndicatorInsets) {
368366
_scrollView.scrollIndicatorInsets = RCTUIEdgeInsetsFromEdgeInsets(newScrollViewProps.scrollIndicatorInsets);
@@ -702,6 +700,7 @@ - (void)prepareForRecycle
702700
// and keeps it as an opt-in behavior.
703701
_scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
704702
_shouldUpdateContentInsetAdjustmentBehavior = YES;
703+
_automaticallyAdjustKeyboardInsets = NO;
705704
_isUserTriggeredScrolling = NO;
706705
CGRect oldFrame = self.frame;
707706
self.frame = CGRectZero;
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#import <React/RCTScrollViewComponentView.h>
9+
#import <XCTest/XCTest.h>
10+
#import <react/renderer/components/scrollview/ScrollViewProps.h>
11+
#import <react/renderer/components/scrollview/ScrollViewShadowNode.h>
12+
13+
using namespace facebook::react;
14+
15+
#if TARGET_OS_IOS
16+
17+
static Props::Shared makeScrollViewProps(bool automaticallyAdjustKeyboardInsets)
18+
{
19+
auto props = std::make_shared<ScrollViewProps>();
20+
props->automaticallyAdjustKeyboardInsets = automaticallyAdjustKeyboardInsets;
21+
return props;
22+
}
23+
24+
@interface RCTScrollViewComponentView (Tests)
25+
- (void)_keyboardWillChangeFrame:(NSNotification *)notification;
26+
@end
27+
28+
@interface RCTScrollViewComponentViewTests : XCTestCase
29+
@end
30+
31+
@implementation RCTScrollViewComponentViewTests
32+
33+
- (void)testAutomaticallyAdjustKeyboardInsetsAcrossRecycling
34+
{
35+
RCTScrollViewComponentView *view = [[RCTScrollViewComponentView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
36+
auto props = makeScrollViewProps(true);
37+
[view updateProps:props oldProps:ScrollViewShadowNode::defaultSharedProps()];
38+
39+
NSNotification *notification = [NSNotification
40+
notificationWithName:UIKeyboardWillChangeFrameNotification
41+
object:nil
42+
userInfo:@{
43+
UIKeyboardAnimationDurationUserInfoKey : @0,
44+
UIKeyboardAnimationCurveUserInfoKey : @(UIViewAnimationCurveLinear),
45+
UIKeyboardFrameBeginUserInfoKey : [NSValue valueWithCGRect:CGRectMake(0, 100, 100, 50)],
46+
UIKeyboardFrameEndUserInfoKey : [NSValue valueWithCGRect:CGRectMake(0, 50, 100, 50)],
47+
}];
48+
49+
[view _keyboardWillChangeFrame:notification];
50+
XCTAssertEqual(view.scrollView.contentInset.bottom, 50);
51+
52+
[view prepareForRecycle];
53+
[view _keyboardWillChangeFrame:notification];
54+
XCTAssertTrue(UIEdgeInsetsEqualToEdgeInsets(view.scrollView.contentInset, UIEdgeInsetsZero));
55+
56+
[view updateProps:props oldProps:nullptr];
57+
[view _keyboardWillChangeFrame:notification];
58+
XCTAssertEqual(view.scrollView.contentInset.bottom, 50);
59+
}
60+
61+
@end
62+
63+
#endif

0 commit comments

Comments
 (0)