mirror of
https://github.com/status-im/react-native.git
synced 2025-02-24 23:28:12 +00:00
[Nav] Add support for bar button icons and left buttons
Summary: NavigatorIOS supports four new properties: - **rightButtonImageSource:** The source of an image to display in the top right. This must be a static image since UINavigationController only supports UIImages. Adding support for UIImageViews (or arbitrary views) is more complicated because custom views do not fade on touch and do not have hit slop the same way that UIImage buttons do. Usage: `rightButtonImageSource: ix('ImageName')` - **backButtonImageSource:** Use a custom image for the back button. This does not replace the back caret (`<`) but instead replaces the text next to it. - **leftButtonTitle**: Text for the left nav button, which supersedes the previous nav item's back button when specified. The main use case for this is your initial screen/UIVC which has nothing to go back to (since it is the first VC on the stack) but need to display a left button. This does hide the back button if there would have been one otherwise. - **leftButtonImageSource:** Image source for the left button, super Closes https://github.com/facebook/react-native/pull/263 Github Author: James Ide <ide@jameside.com> Test Plan: Imported from GitHub, without a `Test Plan:` line.
This commit is contained in:
parent
b8bf4d0957
commit
b97ce93cea
@ -39,3 +39,8 @@ declare module 'image!uie_thumb_selected' {
|
||||
declare var uri: string;
|
||||
declare var isStatic: boolean;
|
||||
}
|
||||
|
||||
declare module 'image!NavBarButtonPlus' {
|
||||
declare var uri: string;
|
||||
declare var isStatic: boolean;
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ var React = require('react-native');
|
||||
var ViewExample = require('./ViewExample');
|
||||
var createExamplePage = require('./createExamplePage');
|
||||
var {
|
||||
AlertIOS,
|
||||
PixelRatio,
|
||||
ScrollView,
|
||||
StyleSheet,
|
||||
@ -92,6 +93,30 @@ var NavigatorIOSExample = React.createClass({
|
||||
}
|
||||
});
|
||||
})}
|
||||
{this._renderRow('Custom Left & Right Icons', () => {
|
||||
this.props.navigator.push({
|
||||
title: NavigatorIOSExample.title,
|
||||
component: EmptyPage,
|
||||
leftButtonTitle: 'Custom Left',
|
||||
onLeftButtonPress: () => this.props.navigator.pop(),
|
||||
rightButtonIcon: require('image!NavBarButtonPlus'),
|
||||
onRightButtonPress: () => {
|
||||
AlertIOS.alert(
|
||||
'Bar Button Action',
|
||||
'Recognized a tap on the bar button icon',
|
||||
[
|
||||
{
|
||||
text: 'OK',
|
||||
onPress: () => console.log('Tapped OK'),
|
||||
},
|
||||
]
|
||||
);
|
||||
},
|
||||
passProps: {
|
||||
text: 'This page has an icon for the right button in the nav bar',
|
||||
}
|
||||
});
|
||||
})}
|
||||
{this._renderRow('Pop', () => {
|
||||
this.props.navigator.pop();
|
||||
})}
|
||||
|
21
Examples/UIExplorer/UIExplorer/Images.xcassets/NavBarButtonPlus.imageset/Contents.json
vendored
Normal file
21
Examples/UIExplorer/UIExplorer/Images.xcassets/NavBarButtonPlus.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "NavBarButtonPlus@3x.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
Examples/UIExplorer/UIExplorer/Images.xcassets/NavBarButtonPlus.imageset/NavBarButtonPlus@3x.png
vendored
Normal file
BIN
Examples/UIExplorer/UIExplorer/Images.xcassets/NavBarButtonPlus.imageset/NavBarButtonPlus@3x.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 166 B |
@ -12,6 +12,7 @@
|
||||
'use strict';
|
||||
|
||||
var EventEmitter = require('EventEmitter');
|
||||
var Image = require('Image');
|
||||
var React = require('React');
|
||||
var ReactIOSViewAttributes = require('ReactIOSViewAttributes');
|
||||
var RCTNavigatorManager = require('NativeModules').NavigatorManager;
|
||||
@ -47,11 +48,16 @@ var RCTNavigatorItem = createReactIOSNativeComponentClass({
|
||||
// NavigatorIOS does not use them all, because some are problematic
|
||||
title: true,
|
||||
barTintColor: true,
|
||||
leftButtonIcon: true,
|
||||
leftButtonTitle: true,
|
||||
onNavLeftButtonTap: true,
|
||||
rightButtonIcon: true,
|
||||
rightButtonTitle: true,
|
||||
onNavRightButtonTap: true,
|
||||
backButtonIcon: true,
|
||||
backButtonTitle: true,
|
||||
tintColor: true,
|
||||
navigationBarHidden: true,
|
||||
backButtonTitle: true,
|
||||
titleTextColor: true,
|
||||
style: true,
|
||||
},
|
||||
@ -79,7 +85,12 @@ type Route = {
|
||||
title: string;
|
||||
passProps: Object;
|
||||
backButtonTitle: string;
|
||||
backButtonIcon: Object;
|
||||
leftButtonTitle: string;
|
||||
leftButtonIcon: Object;
|
||||
onLeftButtonPress: Function;
|
||||
rightButtonTitle: string;
|
||||
rightButtonIcon: Object;
|
||||
onRightButtonPress: Function;
|
||||
wrapperStyle: any;
|
||||
};
|
||||
@ -212,6 +223,13 @@ var NavigatorIOS = React.createClass({
|
||||
*/
|
||||
passProps: PropTypes.object,
|
||||
|
||||
/**
|
||||
* If set, the left header button image will appear with this source. Note
|
||||
* that this doesn't apply for the header of the current view, but the
|
||||
* ones of the views that are pushed afterward.
|
||||
*/
|
||||
backButtonIcon: Image.propTypes.source,
|
||||
|
||||
/**
|
||||
* If set, the left header button will appear with this name. Note that
|
||||
* this doesn't apply for the header of the current view, but the ones
|
||||
@ -219,6 +237,26 @@ var NavigatorIOS = React.createClass({
|
||||
*/
|
||||
backButtonTitle: PropTypes.string,
|
||||
|
||||
/**
|
||||
* If set, the left header button image will appear with this source
|
||||
*/
|
||||
leftButtonIcon: Image.propTypes.source,
|
||||
|
||||
/**
|
||||
* If set, the left header button will appear with this name
|
||||
*/
|
||||
leftButtonTitle: PropTypes.string,
|
||||
|
||||
/**
|
||||
* Called when the left header button is pressed
|
||||
*/
|
||||
onLeftButtonPress: PropTypes.func,
|
||||
|
||||
/**
|
||||
* If set, the right header button image will appear with this source
|
||||
*/
|
||||
rightButtonIcon: Image.propTypes.source,
|
||||
|
||||
/**
|
||||
* If set, the right header button will appear with this name
|
||||
*/
|
||||
@ -560,7 +598,12 @@ var NavigatorIOS = React.createClass({
|
||||
this.props.itemWrapperStyle,
|
||||
route.wrapperStyle
|
||||
]}
|
||||
backButtonIcon={this._imageNameFromSource(route.backButtonIcon)}
|
||||
backButtonTitle={route.backButtonTitle}
|
||||
leftButtonIcon={this._imageNameFromSource(route.leftButtonIcon)}
|
||||
leftButtonTitle={route.leftButtonTitle}
|
||||
onNavLeftButtonTap={route.onLeftButtonPress}
|
||||
rightButtonIcon={this._imageNameFromSource(route.rightButtonIcon)}
|
||||
rightButtonTitle={route.rightButtonTitle}
|
||||
onNavRightButtonTap={route.onRightButtonPress}
|
||||
navigationBarHidden={this.props.navigationBarHidden}
|
||||
@ -577,6 +620,10 @@ var NavigatorIOS = React.createClass({
|
||||
);
|
||||
},
|
||||
|
||||
_imageNameFromSource: function(source: ?Object) {
|
||||
return source ? source.uri : undefined;
|
||||
},
|
||||
|
||||
renderNavigationStackItems: function() {
|
||||
var shouldRecurseToNavigator =
|
||||
this.state.makingNavigatorRequest ||
|
||||
|
@ -1159,6 +1159,12 @@ RCT_EXPORT_METHOD(clearJSResponder)
|
||||
@"captured": @"onNavigationCompleteCapture"
|
||||
}
|
||||
},
|
||||
@"topNavLeftButtonTap": @{
|
||||
@"phasedRegistrationNames": @{
|
||||
@"bubbled": @"onNavLeftButtonTap",
|
||||
@"captured": @"onNavLefttButtonTapCapture"
|
||||
}
|
||||
},
|
||||
@"topNavRightButtonTap": @{
|
||||
@"phasedRegistrationNames": @{
|
||||
@"bubbled": @"onNavRightButtonTap",
|
||||
|
@ -12,11 +12,19 @@
|
||||
@interface RCTNavItem : UIView
|
||||
|
||||
@property (nonatomic, copy) NSString *title;
|
||||
@property (nonatomic, strong) UIImage *leftButtonIcon;
|
||||
@property (nonatomic, copy) NSString *leftButtonTitle;
|
||||
@property (nonatomic, strong) UIImage *rightButtonIcon;
|
||||
@property (nonatomic, copy) NSString *rightButtonTitle;
|
||||
@property (nonatomic, strong) UIImage *backButtonIcon;
|
||||
@property (nonatomic, copy) NSString *backButtonTitle;
|
||||
@property (nonatomic, assign) BOOL navigationBarHidden;
|
||||
@property (nonatomic, copy) UIColor *tintColor;
|
||||
@property (nonatomic, copy) UIColor *barTintColor;
|
||||
@property (nonatomic, copy) UIColor *titleTextColor;
|
||||
@property (nonatomic, strong) UIColor *tintColor;
|
||||
@property (nonatomic, strong) UIColor *barTintColor;
|
||||
@property (nonatomic, strong) UIColor *titleTextColor;
|
||||
|
||||
@property (nonatomic, readonly) UIBarButtonItem *backButtonItem;
|
||||
@property (nonatomic, readonly) UIBarButtonItem *leftButtonItem;
|
||||
@property (nonatomic, readonly) UIBarButtonItem *rightButtonItem;
|
||||
|
||||
@end
|
||||
|
@ -11,5 +11,104 @@
|
||||
|
||||
@implementation RCTNavItem
|
||||
|
||||
@end
|
||||
@synthesize backButtonItem = _backButtonItem;
|
||||
@synthesize leftButtonItem = _leftButtonItem;
|
||||
@synthesize rightButtonItem = _rightButtonItem;
|
||||
|
||||
- (void)setBackButtonTitle:(NSString *)backButtonTitle
|
||||
{
|
||||
_backButtonTitle = backButtonTitle;
|
||||
_backButtonItem = nil;
|
||||
}
|
||||
|
||||
- (void)setBackButtonIcon:(UIImage *)backButtonIcon
|
||||
{
|
||||
_backButtonIcon = backButtonIcon;
|
||||
_backButtonItem = nil;
|
||||
}
|
||||
|
||||
- (UIBarButtonItem *)backButtonItem
|
||||
{
|
||||
if (!_backButtonItem) {
|
||||
if (_backButtonIcon) {
|
||||
_backButtonItem = [[UIBarButtonItem alloc] initWithImage:_backButtonIcon
|
||||
style:UIBarButtonItemStylePlain
|
||||
target:nil
|
||||
action:nil];
|
||||
} else if (_backButtonTitle.length) {
|
||||
_backButtonItem = [[UIBarButtonItem alloc] initWithTitle:_backButtonTitle
|
||||
style:UIBarButtonItemStylePlain
|
||||
target:nil
|
||||
action:nil];
|
||||
} else {
|
||||
_backButtonItem = nil;
|
||||
}
|
||||
}
|
||||
return _backButtonItem;
|
||||
}
|
||||
|
||||
- (void)setLeftButtonTitle:(NSString *)leftButtonTitle
|
||||
{
|
||||
_leftButtonTitle = leftButtonTitle;
|
||||
_leftButtonItem = nil;
|
||||
}
|
||||
|
||||
- (void)setLeftButtonIcon:(UIImage *)leftButtonIcon
|
||||
{
|
||||
_leftButtonIcon = leftButtonIcon;
|
||||
_leftButtonIcon = nil;
|
||||
}
|
||||
|
||||
- (UIBarButtonItem *)leftButtonItem
|
||||
{
|
||||
if (!_leftButtonItem) {
|
||||
if (_leftButtonIcon) {
|
||||
_leftButtonItem = [[UIBarButtonItem alloc] initWithImage:_leftButtonIcon
|
||||
style:UIBarButtonItemStylePlain
|
||||
target:nil
|
||||
action:nil];
|
||||
} else if (_leftButtonTitle.length) {
|
||||
_leftButtonItem = [[UIBarButtonItem alloc] initWithTitle:_leftButtonTitle
|
||||
style:UIBarButtonItemStylePlain
|
||||
target:nil
|
||||
action:nil];
|
||||
} else {
|
||||
_leftButtonItem = nil;
|
||||
}
|
||||
}
|
||||
return _leftButtonItem;
|
||||
}
|
||||
|
||||
- (void)setRightButtonTitle:(NSString *)rightButtonTitle
|
||||
{
|
||||
_rightButtonTitle = rightButtonTitle;
|
||||
_rightButtonItem = nil;
|
||||
}
|
||||
|
||||
- (void)setRightButtonIcon:(UIImage *)rightButtonIcon
|
||||
{
|
||||
_rightButtonIcon = rightButtonIcon;
|
||||
_rightButtonItem = nil;
|
||||
}
|
||||
|
||||
- (UIBarButtonItem *)rightButtonItem
|
||||
{
|
||||
if (!_rightButtonItem) {
|
||||
if (_rightButtonIcon) {
|
||||
_rightButtonItem = [[UIBarButtonItem alloc] initWithImage:_rightButtonIcon
|
||||
style:UIBarButtonItemStylePlain
|
||||
target:nil
|
||||
action:nil];
|
||||
} else if (_rightButtonTitle.length) {
|
||||
_rightButtonItem = [[UIBarButtonItem alloc] initWithTitle:_rightButtonTitle
|
||||
style:UIBarButtonItemStylePlain
|
||||
target:nil
|
||||
action:nil];
|
||||
} else {
|
||||
_rightButtonItem = nil;
|
||||
}
|
||||
}
|
||||
return _rightButtonItem;
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -21,12 +21,20 @@ RCT_EXPORT_MODULE()
|
||||
return [[RCTNavItem alloc] init];
|
||||
}
|
||||
|
||||
RCT_EXPORT_VIEW_PROPERTY(navigationBarHidden, BOOL)
|
||||
RCT_EXPORT_VIEW_PROPERTY(tintColor, UIColor)
|
||||
RCT_EXPORT_VIEW_PROPERTY(barTintColor, UIColor)
|
||||
|
||||
RCT_EXPORT_VIEW_PROPERTY(title, NSString)
|
||||
RCT_EXPORT_VIEW_PROPERTY(rightButtonTitle, NSString);
|
||||
RCT_EXPORT_VIEW_PROPERTY(backButtonTitle, NSString);
|
||||
RCT_EXPORT_VIEW_PROPERTY(navigationBarHidden, BOOL);
|
||||
RCT_EXPORT_VIEW_PROPERTY(tintColor, UIColor);
|
||||
RCT_EXPORT_VIEW_PROPERTY(barTintColor, UIColor);
|
||||
RCT_EXPORT_VIEW_PROPERTY(titleTextColor, UIColor);
|
||||
RCT_EXPORT_VIEW_PROPERTY(titleTextColor, UIColor)
|
||||
|
||||
RCT_EXPORT_VIEW_PROPERTY(backButtonIcon, UIImage)
|
||||
RCT_EXPORT_VIEW_PROPERTY(backButtonTitle, NSString)
|
||||
|
||||
RCT_EXPORT_VIEW_PROPERTY(leftButtonTitle, NSString)
|
||||
RCT_EXPORT_VIEW_PROPERTY(leftButtonIcon, UIImage)
|
||||
|
||||
RCT_EXPORT_VIEW_PROPERTY(rightButtonIcon, UIImage)
|
||||
RCT_EXPORT_VIEW_PROPERTY(rightButtonTitle, NSString)
|
||||
|
||||
@end
|
||||
|
@ -64,7 +64,6 @@
|
||||
// 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];
|
||||
@ -73,33 +72,23 @@
|
||||
return;
|
||||
}
|
||||
|
||||
self.navigationItem.title = _navItem.title;
|
||||
|
||||
UINavigationBar *bar = self.navigationController.navigationBar;
|
||||
if (_navItem.barTintColor) {
|
||||
bar.barTintColor = _navItem.barTintColor;
|
||||
}
|
||||
if (_navItem.tintColor) {
|
||||
bar.tintColor = _navItem.tintColor;
|
||||
}
|
||||
if (_navItem.titleTextColor) {
|
||||
[bar setTitleTextAttributes:@{NSForegroundColorAttributeName : _navItem.titleTextColor}];
|
||||
}
|
||||
|
||||
if (_navItem.rightButtonTitle.length > 0) {
|
||||
self.navigationItem.rightBarButtonItem =
|
||||
[[UIBarButtonItem alloc] initWithTitle:_navItem.rightButtonTitle
|
||||
style:UIBarButtonItemStyleDone
|
||||
target:self
|
||||
action:@selector(handleNavRightButtonTapped)];
|
||||
UINavigationItem *item = self.navigationItem;
|
||||
item.title = _navItem.title;
|
||||
item.backBarButtonItem = _navItem.backButtonItem;
|
||||
if ((item.leftBarButtonItem = _navItem.leftButtonItem)) {
|
||||
item.leftBarButtonItem.target = self;
|
||||
item.leftBarButtonItem.action = @selector(handleNavLeftButtonTapped);
|
||||
}
|
||||
|
||||
if (_navItem.backButtonTitle.length > 0) {
|
||||
self.navigationItem.backBarButtonItem =
|
||||
[[UIBarButtonItem alloc] initWithTitle:_navItem.backButtonTitle
|
||||
style:UIBarButtonItemStylePlain
|
||||
target:nil
|
||||
action:nil];
|
||||
if ((item.rightBarButtonItem = _navItem.rightButtonItem)) {
|
||||
item.rightBarButtonItem.target = self;
|
||||
item.rightBarButtonItem.action = @selector(handleNavRightButtonTapped);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -114,6 +103,12 @@
|
||||
self.view = _wrapperView;
|
||||
}
|
||||
|
||||
- (void)handleNavLeftButtonTapped
|
||||
{
|
||||
[_eventDispatcher sendInputEventWithName:@"topNavLeftButtonTap"
|
||||
body:@{@"target":_navItem.reactTag}];
|
||||
}
|
||||
|
||||
- (void)handleNavRightButtonTapped
|
||||
{
|
||||
[_eventDispatcher sendInputEventWithName:@"topNavRightButtonTap"
|
||||
|
Loading…
x
Reference in New Issue
Block a user