diff --git a/README.md b/README.md index 4e983128331..ec3949b5240 100644 --- a/README.md +++ b/README.md @@ -125,8 +125,8 @@ v2 is written in Test Driven Development. We have a test for every feature inclu | screenBackgroundColor | ✅ | [Contribute](/docs/docs/CONTRIBUTING.md) | Wix| | orientation | ✅ | [Contribute](/docs/docs/CONTRIBUTING.md) | Wix| | disabledBackGesture | ✅ | / iOS specific | -| screenBackgroundImageName | [Contribute](/docs/docs/CONTRIBUTING.md) | [Contribute](/docs/docs/CONTRIBUTING.md) | -| rootBackgroundImageName | [Contribute](/docs/docs/CONTRIBUTING.md) | [Contribute](/docs/docs/CONTRIBUTING.md) | +| screenBackgroundImageName | ✅ | [Contribute](/docs/docs/CONTRIBUTING.md) | +| rootBackgroundImageName | ✅ | [Contribute](/docs/docs/CONTRIBUTING.md) | | sideMenuVisible | [Contribute](/docs/docs/CONTRIBUTING.md) | [Contribute](/docs/docs/CONTRIBUTING.md) | @@ -193,8 +193,8 @@ Note: v1 properties with names beginning with 'navBar' are replaced in v2 with | statusBarHideWithTopBar | ✅ | ✅ | [Contribute](/docs/docs/CONTRIBUTING.md) | @gtchance| | statusBarHidden | ✅ | ✅ | [Contribute](/docs/docs/CONTRIBUTING.md) | WIX | | disabledBackGesture | ✅ | ✅ | / iOS specific | -| screenBackgroundImageName | ✅ | [Contribute](/docs/docs/CONTRIBUTING.md) | [Contribute](/docs/docs/CONTRIBUTING.md) | -| rootBackgroundImageName | ✅ | [Contribute](/docs/docs/CONTRIBUTING.md) | [Contribute](/docs/docs/CONTRIBUTING.md) | +| screenBackgroundImageName | ✅ | ✅ | [Contribute](/docs/docs/CONTRIBUTING.md) | +| rootBackgroundImageName | ✅ | ✅ | [Contribute](/docs/docs/CONTRIBUTING.md) | | setButtons | ✅ | ✅ | [Contribute](/docs/docs/CONTRIBUTING.md) | @Johan-dutoit| | title | ✅ | ✅ | ✅| Wix| | toggleDrawer | ✅ | ✅ | [Contribute](/docs/docs/CONTRIBUTING.md) | diff --git a/lib/ios/RNNNavigationOptions.h b/lib/ios/RNNNavigationOptions.h index 0113eb0bea4..e62eb3c2c32 100644 --- a/lib/ios/RNNNavigationOptions.h +++ b/lib/ios/RNNNavigationOptions.h @@ -23,7 +23,8 @@ extern const NSInteger TOP_BAR_TRANSPARENT_TAG; @property (nonatomic, strong) RNNTopBarOptions* topBar; @property (nonatomic, strong) RNNTabBarOptions* bottomTabs; @property (nonatomic, strong) RNNSideMenuOptions* sideMenu; - +@property (nonatomic, strong) UIImage* backgroundImage; +@property (nonatomic, strong) UIImage* rootBackgroundImage; - (UIInterfaceOrientationMask)supportedOrientations; diff --git a/lib/ios/RNNNavigationOptions.m b/lib/ios/RNNNavigationOptions.m index 33ee18050a4..3d5d165b3fe 100644 --- a/lib/ios/RNNNavigationOptions.m +++ b/lib/ios/RNNNavigationOptions.m @@ -28,7 +28,9 @@ -(instancetype)initWithDict:(NSDictionary *)navigationOptions { self.topBar = [[RNNTopBarOptions alloc] initWithDict:[navigationOptions objectForKey:@"topBar"]]; self.bottomTabs = [[RNNTabBarOptions alloc] initWithDict:[navigationOptions objectForKey:@"bottomTabs"]]; self.sideMenu = [[RNNSideMenuOptions alloc] initWithDict:[navigationOptions objectForKey:@"sideMenu"]]; - + self.backgroundImage = [RCTConvert UIImage:[navigationOptions objectForKey:@"backgroundImage"]]; + self.rootBackgroundImage = [RCTConvert UIImage:[navigationOptions objectForKey:@"rootBackgroundImage"]]; + return self; } @@ -257,6 +259,30 @@ -(void)applyOn:(UIViewController*)viewController { [self.sideMenu resetOptions]; } + + if (self.backgroundImage) { + UIImageView* backgroundImageView = (viewController.view.subviews.count > 0) ? viewController.view.subviews[0] : nil; + if (![backgroundImageView isKindOfClass:[UIImageView class]]) { + backgroundImageView = [[UIImageView alloc] initWithFrame:viewController.view.bounds]; + [viewController.view insertSubview:backgroundImageView atIndex:0]; + } + + backgroundImageView.layer.masksToBounds = YES; + backgroundImageView.image = self.backgroundImage; + [backgroundImageView setContentMode:UIViewContentModeScaleAspectFill]; + } + + if (self.rootBackgroundImage) { + UIImageView* backgroundImageView = (viewController.navigationController.view.subviews.count > 0) ? viewController.navigationController.view.subviews[0] : nil; + if (![backgroundImageView isKindOfClass:[UIImageView class]]) { + backgroundImageView = [[UIImageView alloc] initWithFrame:viewController.view.bounds]; + [viewController.navigationController.view insertSubview:backgroundImageView atIndex:0]; + } + + backgroundImageView.layer.masksToBounds = YES; + backgroundImageView.image = self.rootBackgroundImage; + [backgroundImageView setContentMode:UIViewContentModeScaleAspectFill]; + } } - (UIInterfaceOrientationMask)supportedOrientations { diff --git a/lib/ios/ReactNativeNavigationTests/RNNRootViewControllerTest.m b/lib/ios/ReactNativeNavigationTests/RNNRootViewControllerTest.m index eab35a51193..32044094cd4 100644 --- a/lib/ios/ReactNativeNavigationTests/RNNRootViewControllerTest.m +++ b/lib/ios/ReactNativeNavigationTests/RNNRootViewControllerTest.m @@ -513,6 +513,22 @@ -(void)testTopBarBlur_true { XCTAssertNotNil([self.uut.navigationController.navigationBar viewWithTag:BLUR_TOPBAR_TAG]); } +-(void)testBackgroundImage { + UIImage* backgroundImage = [[UIImage alloc] init]; + self.options.backgroundImage = backgroundImage; + __unused UINavigationController* nav = [[UINavigationController alloc] initWithRootViewController:self.uut]; + [self.uut viewWillAppear:false]; + XCTAssertTrue([[(UIImageView*)self.uut.view.subviews[0] image] isEqual:backgroundImage]); +} + +-(void)testRootBackgroundImage { + UIImage* rootBackgroundImage = [[UIImage alloc] init]; + self.options.rootBackgroundImage = rootBackgroundImage; + __unused UINavigationController* nav = [[UINavigationController alloc] initWithRootViewController:self.uut]; + [self.uut viewWillAppear:false]; + XCTAssertTrue([[(UIImageView*)self.uut.navigationController.view.subviews[0] image] isEqual:rootBackgroundImage]); +} + -(void)testTopBarDrawUnder_true { self.options.topBar.drawUnder = @(1); __unused UINavigationController* nav = [[UINavigationController alloc] initWithRootViewController:self.uut]; diff --git a/lib/src/commands/OptionsProcessor.js b/lib/src/commands/OptionsProcessor.js index 2a66ed84b1f..0bad8abd777 100644 --- a/lib/src/commands/OptionsProcessor.js +++ b/lib/src/commands/OptionsProcessor.js @@ -5,14 +5,16 @@ const resolveAssetSource = require('react-native/Libraries/Image/resolveAssetSou class OptionsProcessor { static processOptions(navigationOptions) { _.forEach(navigationOptions, (value, key) => { - if (_.endsWith(key, 'Color')) { - navigationOptions[key] = processColor(value); - } - if (_.isEqual(key, 'icon') || _.endsWith(key, 'Icon') || _.endsWith(key, 'Image')) { - navigationOptions[key] = resolveAssetSource(navigationOptions[key]); - } - if (_.isObject(value) || _.isArray(value)) { - OptionsProcessor.processOptions(value); + if (value) { + if (_.endsWith(key, 'Color')) { + navigationOptions[key] = processColor(value); + } + if (_.isEqual(key, 'icon') || _.endsWith(key, 'Icon') || _.endsWith(key, 'Image')) { + navigationOptions[key] = resolveAssetSource(navigationOptions[key]); + } + if (_.isObject(value) || _.isArray(value)) { + OptionsProcessor.processOptions(value); + } } }); } diff --git a/lib/src/commands/OptionsProcessor.test.js b/lib/src/commands/OptionsProcessor.test.js index d645a4df628..dd65ca87b92 100644 --- a/lib/src/commands/OptionsProcessor.test.js +++ b/lib/src/commands/OptionsProcessor.test.js @@ -103,4 +103,11 @@ describe('navigation options', () => { expect(navigationOptionsObj.topBar.textColor).toEqual(0xffff0000); }); + + it('undefined value return undefined ', () => { + navigationOptions.someImage = undefined; + OptionsProcessor.processOptions(navigationOptions); + + expect(navigationOptions.someImage).toEqual(undefined); + }); }); diff --git a/lib/src/params/NavigationOptions.js b/lib/src/params/NavigationOptions.js index 0c7bbe38769..b3a4d24dc6f 100644 --- a/lib/src/params/NavigationOptions.js +++ b/lib/src/params/NavigationOptions.js @@ -27,6 +27,9 @@ class NavigationOptions { this.rightButtons = options.rightButtons && options.rightButtons.map((button) => new Button(button)); this.leftButtons = options.leftButtons && options.leftButtons.map((button) => new Button(button)); this.sideMenu = options.sideMenu; + this.backgroundImage = options.backgroundImage; + this.rootBackgroundImage = options.rootBackgroundImage; + this.screenBackgroundColor = options.screenBackgroundColor; } }