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 45c69b13f4b9..65a8d43b655d 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm @@ -959,12 +959,13 @@ - (void)scrollTo:(double)x y:(double)y animated:(BOOL)animated - (void)scrollToEnd:(BOOL)animated { BOOL isHorizontal = _scrollView.contentSize.width > self.frame.size.width; + UIEdgeInsets contentInset = _scrollView.adjustedContentInset; CGPoint offset; if (isHorizontal) { - CGFloat offsetX = _scrollView.contentSize.width - _scrollView.bounds.size.width + _scrollView.contentInset.right; + CGFloat offsetX = _scrollView.contentSize.width - _scrollView.bounds.size.width + contentInset.right; offset = CGPointMake(fmax(offsetX, 0), 0); } else { - CGFloat offsetY = _scrollView.contentSize.height - _scrollView.bounds.size.height + _scrollView.contentInset.bottom; + CGFloat offsetY = _scrollView.contentSize.height - _scrollView.bounds.size.height + contentInset.bottom; offset = CGPointMake(0, fmax(offsetY, 0)); } diff --git a/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj b/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj index 2f6e9c5ea8d2..80fb6b916a74 100644 --- a/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj +++ b/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj @@ -17,6 +17,7 @@ 5C60EB1C226440DB0018C04F /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5C60EB1B226440DB0018C04F /* AppDelegate.mm */; }; 8145AE06241172D900A3F8DA /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8145AE05241172D900A3F8DA /* LaunchScreen.storyboard */; }; 832F45BB2A8A6E1F0097B4E6 /* SwiftTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 832F45BA2A8A6E1F0097B4E6 /* SwiftTest.swift */; }; + A11A00000000000000000002 /* RCTScrollViewComponentViewTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = A11A00000000000000000001 /* RCTScrollViewComponentViewTests.mm */; }; A975CA6C2C05EADF0043F72A /* RCTNetworkTaskTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A975CA6B2C05EADE0043F72A /* RCTNetworkTaskTests.m */; }; C175B6D9ED9336FB66637943 /* libPods-RNTester.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C706D402EE4AF9BE838CBA9 /* libPods-RNTester.a */; }; CD10C7A5290BD4EB0033E1ED /* RCTEventEmitterTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CD10C7A4290BD4EB0033E1ED /* RCTEventEmitterTests.m */; }; @@ -95,6 +96,7 @@ 8145AE05241172D900A3F8DA /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = RNTester/LaunchScreen.storyboard; sourceTree = ""; }; 832F45BA2A8A6E1F0097B4E6 /* SwiftTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = SwiftTest.swift; path = RNTester/SwiftTest.swift; sourceTree = ""; }; 93A243F0D4D5C54911E811C4 /* libPods-RNTesterIntegrationTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RNTesterIntegrationTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + A11A00000000000000000001 /* RCTScrollViewComponentViewTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RCTScrollViewComponentViewTests.mm; sourceTree = ""; }; A975CA6B2C05EADE0043F72A /* RCTNetworkTaskTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RCTNetworkTaskTests.m; sourceTree = ""; }; AC474BFB29BBD4A1002BDAED /* RNTester.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; name = RNTester.xctestplan; path = RNTester/RNTester.xctestplan; sourceTree = ""; }; B0E70A8A05E03E868F8703FE /* Pods-RNTesterIntegrationTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNTesterIntegrationTests.release.xcconfig"; path = "Target Support Files/Pods-RNTesterIntegrationTests/Pods-RNTesterIntegrationTests.release.xcconfig"; sourceTree = ""; }; @@ -337,6 +339,7 @@ F1A0B1C23D4E5F6071829301 /* RCTTurboModuleArrayBufferTests.mm */, E7DB20CF22B2BAA5005AC45F /* RCTMultipartStreamReaderTests.m */, A975CA6B2C05EADE0043F72A /* RCTNetworkTaskTests.m */, + A11A00000000000000000001 /* RCTScrollViewComponentViewTests.mm */, E7DB20BE22B2BAA4005AC45F /* RCTNativeAnimatedNodesManagerTests.m */, E7DB20AD22B2BAA3005AC45F /* RCTPerformanceLoggerTests.m */, E7DB20C122B2BAA4005AC45F /* RCTUnicodeDecodeTests.m */, @@ -767,6 +770,7 @@ E7DB20E422B2BAA6005AC45F /* RCTFormatErrorTests.m in Sources */, E7DB20EB22B2BAA6005AC45F /* RCTConvert_YGValueTests.m in Sources */, E7DB20E922B2BAA6005AC45F /* RCTComponentPropsTests.m in Sources */, + A11A00000000000000000002 /* RCTScrollViewComponentViewTests.mm in Sources */, E7DB20D822B2BAA6005AC45F /* RCTJSONTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/packages/rn-tester/RNTesterUnitTests/RCTScrollViewComponentViewTests.mm b/packages/rn-tester/RNTesterUnitTests/RCTScrollViewComponentViewTests.mm new file mode 100644 index 000000000000..d8b634b9b832 --- /dev/null +++ b/packages/rn-tester/RNTesterUnitTests/RCTScrollViewComponentViewTests.mm @@ -0,0 +1,56 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +#import +#import + +@interface RCTScrollViewComponentView (Tests) + +- (void)scrollToEnd:(BOOL)animated; + +@end + +@interface RCTAdjustedContentInsetScrollView : RCTEnhancedScrollView + +@property (nonatomic, assign) UIEdgeInsets testAdjustedContentInset; + +@end + +@implementation RCTAdjustedContentInsetScrollView + +- (UIEdgeInsets)adjustedContentInset +{ + return self.testAdjustedContentInset; +} + +@end + +@interface RCTScrollViewComponentViewTests : XCTestCase + +@end + +@implementation RCTScrollViewComponentViewTests + +- (void)testScrollToEndIncludesAdjustedContentInset +{ + RCTScrollViewComponentView *componentView = + [[RCTScrollViewComponentView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; + RCTAdjustedContentInsetScrollView *scrollView = + [[RCTAdjustedContentInsetScrollView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; + scrollView.contentSize = CGSizeMake(100, 200); + scrollView.contentInset = UIEdgeInsetsZero; + scrollView.testAdjustedContentInset = UIEdgeInsetsMake(0, 0, 20, 0); + componentView.scrollView = scrollView; + + [componentView scrollToEnd:NO]; + + XCTAssertEqualWithAccuracy(componentView.scrollView.contentOffset.y, 120, 0.01); +} + +@end