diff --git a/Examples/UIExplorer/NavigatorIOSExample.js b/Examples/UIExplorer/NavigatorIOSExample.js index 4a2011a654611c..def54a1a8b0ad2 100644 --- a/Examples/UIExplorer/NavigatorIOSExample.js +++ b/Examples/UIExplorer/NavigatorIOSExample.js @@ -32,7 +32,7 @@ var EmptyPage = React.createClass({ render: function() { return ( - + {this.props.text} @@ -48,7 +48,7 @@ var NavigatorIOSExample = React.createClass({ title: '', description: 'iOS navigation capabilities', }, - + counter: 10, render: function() { var recurseTitle = 'Recurse Navigation'; if (!this.props.topExampleRoute) { @@ -82,6 +82,12 @@ var NavigatorIOSExample = React.createClass({ component: createExamplePage(null, ViewExample), }); })} + {this._renderRow('Change rightButtonTitle', () => { + this.props.navigator.updateNavBar({rightButtonTitle:(this.counter++) + "",onRightButtonPress:()=>{ + this.counter = 10; + this.props.navigator.updateNavBar({rightButtonTitle:null}); + }}); + })} {this._renderRow('Custom Right Button', () => { this.props.navigator.push({ title: NavigatorIOSExample.title, @@ -93,6 +99,30 @@ var NavigatorIOSExample = React.createClass({ } }); })} + {this._renderRow('Custom Title Icon', () => { + this.props.navigator.push({ + titleIcon: require('image!uie_thumb_normal'), + component: EmptyPage, + rightButtonTitle: 'Cancel', + onRightButtonPress: () => this.props.navigator.pop(), + passProps: { + text: 'This page has a custom title icon in the nav bar', + } + }); + })} + {this._renderRow('Transparent navigation bar', () => { + this.props.navigator.push({ + titleIcon: require('image!uie_thumb_normal'), + component: EmptyPage, + navigationBarTransparent: true, + rightButtonTitle: 'Cancel', + onRightButtonPress: () => this.props.navigator.pop(), + passProps: { + text: 'This page has a custom title icon and a transparent navigation bar in the nav bar', + customStyle: {backgroundColor:"#527FE4"} + } + }); + })} {this._renderRow('Custom Left & Right Icons', () => { this.props.navigator.push({ title: NavigatorIOSExample.title, diff --git a/Libraries/Components/Navigation/NavigatorIOS.ios.js b/Libraries/Components/Navigation/NavigatorIOS.ios.js index 4c8e1b6e7e3bed..be376d04e28c42 100644 --- a/Libraries/Components/Navigation/NavigatorIOS.ios.js +++ b/Libraries/Components/Navigation/NavigatorIOS.ios.js @@ -19,6 +19,7 @@ var RCTNavigatorManager = require('NativeModules').NavigatorManager; var StyleSheet = require('StyleSheet'); var StaticContainer = require('StaticContainer.react'); var View = require('View'); +var merge = require('merge'); var requireNativeComponent = require('requireNativeComponent'); var invariant = require('invariant'); @@ -52,6 +53,7 @@ var NavigatorTransitionerIOS = React.createClass({ type Route = { component: Function; title: string; + titleIcon?: Object; passProps?: Object; backButtonTitle?: string; backButtonIcon?: Object; @@ -61,6 +63,8 @@ type Route = { rightButtonTitle?: string; rightButtonIcon?: Object; onRightButtonPress?: Function; + navigationBarHidden?: Boolean; + navigationBarTransparent?: Boolean; wrapperStyle?: any; }; @@ -185,6 +189,10 @@ var NavigatorIOS = React.createClass({ * The title displayed in the nav bar and back button for this route */ title: PropTypes.string.isRequired, + /** + * The title icon displayed in the nav bar for this route + */ + titleIcon: Image.propTypes.source, /** * Specify additional props passed to the component. NavigatorIOS will @@ -279,6 +287,11 @@ var NavigatorIOS = React.createClass({ */ translucent: PropTypes.bool, + /** + * A Boolean value that indicates whether the navigation bar is totaly transparent + */ + navigationBarTransparent: PropTypes.bool, + }, navigator: (undefined: ?Object), @@ -298,6 +311,7 @@ var NavigatorIOS = React.createClass({ popToRoute: this.popToRoute, popToTop: this.popToTop, navigationContext: this.navigationContext, + updateNavBar: this.updateNavBar, }; this._emitWillFocus(this.state.routeStack[this.state.observedTopOfStack]); }, @@ -336,6 +350,17 @@ var NavigatorIOS = React.createClass({ updatingAllIndicesAtOrBeyond: 0, }; }, + updateNavBar: function (route: Route){ + if (route !== undefined){ + var current: Route = this.state.routeStack[this.state.routeStack.length - 1] ; + this.state.routeStack[this.state.routeStack.length - 1] = merge(current, route); + } + + this.setState({ + updatingAllIndicesAtOrBeyond:this.state.routeStack.length - 1, + makingNavigatorRequest: true, + }); + }, _toFocusOnNavigationComplete: (undefined: any), @@ -592,12 +617,15 @@ var NavigatorIOS = React.createClass({ _routeToStackItem: function(route: Route, i: number) { var Component = route.component; var shouldUpdateChild = this.state.updatingAllIndicesAtOrBeyond !== null && - this.state.updatingAllIndicesAtOrBeyond >= i; + (i >= this.state.updatingAllIndicesAtOrBeyond); + var navigationBarHidden = route.navigationBarHidden !== undefined ? route.navigationBarHidden : this.props.navigationBarHidden; + var navigationBarTransparent = route.navigationBarTransparent !== undefined ? route.navigationBarTransparent : this.props.navigationBarTransparent; return ( + titleTextColor={this.props.titleTextColor} + navigationBarHidden={navigationBarHidden} + navigationBarTransparent={navigationBarTransparent} > #import "RCTComponent.h" +@class RCTNavItem; + +@protocol RCTNavItemListener + +-(void)update:(RCTNavItem *)itemNav; + +@end @interface RCTNavItem : UIView @property (nonatomic, copy) NSString *title; +@property (nonatomic, strong) UIImage *titleIcon; @property (nonatomic, strong) UIImage *leftButtonIcon; @property (nonatomic, copy) NSString *leftButtonTitle; @property (nonatomic, strong) UIImage *rightButtonIcon; @@ -21,6 +29,7 @@ @property (nonatomic, strong) UIImage *backButtonIcon; @property (nonatomic, copy) NSString *backButtonTitle; @property (nonatomic, assign) BOOL navigationBarHidden; +@property (nonatomic, assign) BOOL navigationBarTransparent; @property (nonatomic, assign) BOOL shadowHidden; @property (nonatomic, strong) UIColor *tintColor; @property (nonatomic, strong) UIColor *barTintColor; @@ -34,4 +43,6 @@ @property (nonatomic, copy) RCTBubblingEventBlock onNavLeftButtonTap; @property (nonatomic, copy) RCTBubblingEventBlock onNavRightButtonTap; +@property (nonatomic, weak) id delegate; + @end diff --git a/React/Views/RCTNavItem.m b/React/Views/RCTNavItem.m index 5e4043f8495f2d..5560e5ebd39e0c 100644 --- a/React/Views/RCTNavItem.m +++ b/React/Views/RCTNavItem.m @@ -14,17 +14,36 @@ @implementation RCTNavItem @synthesize backButtonItem = _backButtonItem; @synthesize leftButtonItem = _leftButtonItem; @synthesize rightButtonItem = _rightButtonItem; +@synthesize navigationBarTransparent = _navigationBarTransparent; +@synthesize title = _title; +@synthesize titleIcon = _titleIcon; + +-(void)setTitleIcon:(UIImage *)titleIcon{ + _titleIcon = titleIcon; + [self.delegate update:self]; +} + +-(void)setTitle:(NSString *)title{ + _title = title; + [self.delegate update:self]; +} +- (void)setNavigationBarTransparent:(BOOL)transparent{ + _navigationBarTransparent = transparent; + [self.delegate update:self]; +} - (void)setBackButtonTitle:(NSString *)backButtonTitle { _backButtonTitle = backButtonTitle; _backButtonItem = nil; + [self.delegate update:self]; } - (void)setBackButtonIcon:(UIImage *)backButtonIcon { _backButtonIcon = backButtonIcon; _backButtonItem = nil; + [self.delegate update:self]; } - (UIBarButtonItem *)backButtonItem @@ -51,12 +70,14 @@ - (void)setLeftButtonTitle:(NSString *)leftButtonTitle { _leftButtonTitle = leftButtonTitle; _leftButtonItem = nil; + [self.delegate update:self]; } - (void)setLeftButtonIcon:(UIImage *)leftButtonIcon { _leftButtonIcon = leftButtonIcon; _leftButtonItem = nil; + [self.delegate update:self]; } - (UIBarButtonItem *)leftButtonItem @@ -93,12 +114,14 @@ - (void)setRightButtonTitle:(NSString *)rightButtonTitle { _rightButtonTitle = rightButtonTitle; _rightButtonItem = nil; + [self.delegate update:self]; } - (void)setRightButtonIcon:(UIImage *)rightButtonIcon { _rightButtonIcon = rightButtonIcon; _rightButtonItem = nil; + [self.delegate update:self]; } - (UIBarButtonItem *)rightButtonItem diff --git a/React/Views/RCTNavItemManager.m b/React/Views/RCTNavItemManager.m index 040b7ffceac590..bb8c20fb1839bc 100644 --- a/React/Views/RCTNavItemManager.m +++ b/React/Views/RCTNavItemManager.m @@ -22,6 +22,8 @@ - (UIView *)view } RCT_EXPORT_VIEW_PROPERTY(navigationBarHidden, BOOL) +RCT_EXPORT_VIEW_PROPERTY(navigationBarTransparent, BOOL) + RCT_EXPORT_VIEW_PROPERTY(shadowHidden, BOOL) RCT_EXPORT_VIEW_PROPERTY(tintColor, UIColor) RCT_EXPORT_VIEW_PROPERTY(barTintColor, UIColor) @@ -29,6 +31,8 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(title, NSString) RCT_EXPORT_VIEW_PROPERTY(titleTextColor, UIColor) +RCT_EXPORT_VIEW_PROPERTY(titleIcon, UIImage) + RCT_EXPORT_VIEW_PROPERTY(backButtonIcon, UIImage) RCT_EXPORT_VIEW_PROPERTY(backButtonTitle, NSString) diff --git a/React/Views/RCTWrapperViewController.h b/React/Views/RCTWrapperViewController.h index 7b24ae7d53072f..15fde3726e509b 100644 --- a/React/Views/RCTWrapperViewController.h +++ b/React/Views/RCTWrapperViewController.h @@ -10,6 +10,8 @@ #import #import "RCTViewControllerProtocol.h" +#import "RCTNavItem.h" + @class RCTNavItem; @class RCTWrapperViewController; @@ -21,7 +23,7 @@ didMoveToNavigationController:(UINavigationController *)navigationController; @end -@interface RCTWrapperViewController : UIViewController +@interface RCTWrapperViewController : UIViewController - (instancetype)initWithContentView:(UIView *)contentView NS_DESIGNATED_INITIALIZER; - (instancetype)initWithNavItem:(RCTNavItem *)navItem; diff --git a/React/Views/RCTWrapperViewController.m b/React/Views/RCTWrapperViewController.m index 92707e683f02ba..bd263a0ec44e6e 100644 --- a/React/Views/RCTWrapperViewController.m +++ b/React/Views/RCTWrapperViewController.m @@ -23,6 +23,8 @@ @implementation RCTWrapperViewController UIView *_contentView; CGFloat _previousTopLayout; CGFloat _previousBottomLayout; + BOOL translusante; + UIImageView *titleView; } @synthesize currentTopLayoutGuide = _currentTopLayoutGuide; @@ -47,8 +49,8 @@ - (instancetype)initWithNavItem:(RCTNavItem *)navItem return self; } -RCT_NOT_IMPLEMENTED(- (instancetype)initWithNibName:(NSString *)nn bundle:(NSBundle *)nb) -RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder) +RCT_NOT_IMPLEMENTED(-initWithNibName:(NSString *)nn bundle:(NSBundle *)nb) +RCT_NOT_IMPLEMENTED(-initWithCoder:(NSCoder *)aDecoder) - (void)viewWillLayoutSubviews { @@ -71,6 +73,10 @@ - (void)viewWillLayoutSubviews } return nil; } +-(void)viewDidLoad{ + [super viewDidLoad]; + translusante = self.navigationController.navigationBar.translucent; +} - (void)viewWillAppear:(BOOL)animated { @@ -79,25 +85,57 @@ - (void)viewWillAppear:(BOOL)animated // TODO: find a way to make this less-tightly coupled to navigation controller if ([self.parentViewController isKindOfClass:[UINavigationController class]]) { - [self.navigationController - setNavigationBarHidden:_navItem.navigationBarHidden - animated:animated]; - - UINavigationBar *bar = self.navigationController.navigationBar; - bar.barTintColor = _navItem.barTintColor; - bar.tintColor = _navItem.tintColor; - bar.translucent = _navItem.translucent; - bar.titleTextAttributes = _navItem.titleTextColor ? @{ - NSForegroundColorAttributeName: _navItem.titleTextColor - } : nil; - - RCTFindNavBarShadowViewInView(bar).hidden = _navItem.shadowHidden; - - UINavigationItem *item = self.navigationItem; - item.title = _navItem.title; - item.backBarButtonItem = _navItem.backButtonItem; - item.leftBarButtonItem = _navItem.leftButtonItem; - item.rightBarButtonItem = _navItem.rightButtonItem; + if (!_navItem) { + return; + } + [self update:_navItem animated:animated]; + } +} + +-(void)update:(RCTNavItem *)navItem { + [self update:navItem animated:NO]; +} +-(void)update:(RCTNavItem *)navItem animated:(BOOL)animated{ + if (!_navItem) { + return; + } + + if (_navItem.navigationBarTransparent) { + [self.navigationController.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault]; + [self.navigationController.navigationBar setTranslucent:YES]; + [self.navigationController.navigationBar setShadowImage:[UIImage new]]; + }else{ + [self.navigationController.navigationBar setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault]; + [self.navigationController.navigationBar setTranslucent:translusante]; + [self.navigationController.navigationBar setShadowImage:nil]; + } + + [self.navigationController setNavigationBarHidden:_navItem.navigationBarHidden animated:animated]; + + RCTFindNavBarShadowViewInView(self.navigationController.navigationBar).hidden = _navItem.shadowHidden; + + _navItem = navItem; + _navItem.delegate = self; + + UINavigationBar *bar = self.navigationController.navigationBar; + bar.barTintColor = _navItem.barTintColor; + bar.tintColor = _navItem.tintColor; + bar.titleTextAttributes = _navItem.titleTextColor ? @{ + NSForegroundColorAttributeName: _navItem.titleTextColor + } : nil; + + UINavigationItem *item = self.navigationItem; + item.title = _navItem.title; + item.backBarButtonItem = _navItem.backButtonItem; + item.leftBarButtonItem = _navItem.leftButtonItem; + item.rightBarButtonItem = _navItem.rightButtonItem; + + if (_navItem.titleIcon){ + if (titleView.image != _navItem.titleIcon){ + titleView = [[UIImageView alloc] initWithImage:_navItem.titleIcon]; + [self.navigationItem setTitleView:titleView]; + } + } }