Browse Source

iOS - Custom navigation bar view (#967)

Custom title view in navigation bar support in `navBarComponentAlignment:'fill' | 'center`
Ran 7 years ago
parent
commit
1320de5d3e

+ 50
- 0
example/src/screens/CustomNavBar.js View File

@@ -0,0 +1,50 @@
1
+import React, {Component} from 'react';
2
+import {
3
+  StyleSheet,
4
+  View,
5
+  TouchableOpacity,
6
+  Text,
7
+  Image
8
+} from 'react-native';
9
+
10
+
11
+export default class CustomNavBar extends Component {
12
+
13
+  constructor(props) {
14
+    super(props);
15
+    this.state = {
16
+    };
17
+  }
18
+
19
+  render() {
20
+    return (
21
+      <View style={styles.container}>
22
+        <TouchableOpacity stye={styles.button} onPress={ () => alert('Thanks for that :)') }>
23
+          <Text style={{color: 'red', textAlign: 'center'}}>Hi Custom</Text>
24
+          <Text style={{textAlign: 'center'}}>Press Me</Text>
25
+        </TouchableOpacity>
26
+
27
+      </View>
28
+    );
29
+  }
30
+}
31
+
32
+const styles = StyleSheet.create({
33
+  container: {
34
+    flex: 1,
35
+    justifyContent: 'center',
36
+    alignItems: 'center',
37
+    backgroundColor: 'transparent'
38
+  },
39
+  button: {
40
+    textAlign: 'center',
41
+    fontSize: 22,
42
+    marginBottom: 10,
43
+    marginTop: 10,
44
+    color: 'blue',
45
+
46
+  }
47
+});
48
+
49
+
50
+

+ 43
- 0
example/src/screens/CustomNavBarScreen.js View File

@@ -0,0 +1,43 @@
1
+import React, {Component} from 'react';
2
+import {
3
+  Text,
4
+  View,
5
+  ScrollView,
6
+  TouchableOpacity,
7
+  StyleSheet,
8
+  Button
9
+} from 'react-native';
10
+
11
+export default class CustomNavBarScreen extends Component {
12
+  static navigatorStyle = {
13
+    drawUnderTabBar: true,
14
+    navBarCustomView: 'example.CustomNavBar'
15
+  };
16
+
17
+
18
+  constructor(props) {
19
+    super(props);
20
+  }
21
+  render() {
22
+    return (
23
+      <View style={styles.container}>
24
+      </View>
25
+    );
26
+  }
27
+
28
+}
29
+
30
+const styles = StyleSheet.create({
31
+  container: {
32
+    flex: 1,
33
+    padding: 20,
34
+    backgroundColor: 'white'
35
+  },
36
+  button: {
37
+    textAlign: 'center',
38
+    fontSize: 18,
39
+    marginBottom: 10,
40
+    marginTop:10,
41
+    color: 'blue'
42
+  }
43
+});

+ 12
- 1
example/src/screens/FirstTabScreen.js View File

@@ -34,7 +34,7 @@ export default class FirstTabScreen extends Component {
34 34
     statusBarTextColorScheme: 'light',
35 35
     tabBarBackgroundColor: '#4dbce9',
36 36
     tabBarButtonColor: '#ffffff',
37
-    tabBarSelectedButtonColor: '#ffff00'
37
+    tabBarSelectedButtonColor: '#ffff00',
38 38
   };
39 39
 
40 40
   constructor(props) {
@@ -69,6 +69,10 @@ export default class FirstTabScreen extends Component {
69 69
           <Text style={styles.button}>Push Styled Screen</Text>
70 70
         </TouchableOpacity>
71 71
 
72
+        <TouchableOpacity onPress={ this.onPushCustomNavBarScreen.bind(this) }>
73
+          <Text style={styles.button}>Push Custom Navigation Bar Screen</Text>
74
+        </TouchableOpacity>
75
+
72 76
         <TouchableOpacity onPress={ this.onModalPress.bind(this) }>
73 77
           <Text style={styles.button}>Show Modal Screen</Text>
74 78
         </TouchableOpacity>
@@ -142,6 +146,13 @@ export default class FirstTabScreen extends Component {
142 146
       }
143 147
     });
144 148
   }
149
+
150
+  onPushCustomNavBarScreen() {
151
+    this.props.navigator.push({
152
+      title: "Custom Nav Bar",
153
+      screen: "example.CustomNavBarScreen"
154
+    });
155
+  }
145 156
 }
146 157
 
147 158
 const styles = StyleSheet.create({

+ 6
- 0
example/src/screens/index.ios.js View File

@@ -8,6 +8,9 @@ import SideMenu from './SideMenu';
8 8
 import ModalScreen from './ModalScreen';
9 9
 import NotificationScreen from './NotificationScreen';
10 10
 import LightBoxScreen from './LightBoxScreen';
11
+import CustomNavBarScreen from './CustomNavBarScreen';
12
+import CustomNavBar from './CustomNavBar';
13
+
11 14
 
12 15
 // register all screens of the app (including internal ones)
13 16
 export function registerScreens() {
@@ -19,4 +22,7 @@ export function registerScreens() {
19 22
   Navigation.registerComponent('example.NotificationScreen', () => NotificationScreen);
20 23
   Navigation.registerComponent('example.SideMenu', () => SideMenu);
21 24
   Navigation.registerComponent('example.LightBoxScreen', () => LightBoxScreen);
25
+
26
+  Navigation.registerComponent('example.CustomNavBarScreen', () => CustomNavBarScreen);
27
+  Navigation.registerComponent('example.CustomNavBar', () => CustomNavBar);
22 28
 }

+ 15
- 0
ios/RCCCustomTitleView.h View File

@@ -0,0 +1,15 @@
1
+//
2
+//  RCCTitleView.h
3
+//  ReactNativeNavigation
4
+//
5
+//  Created by Ran Greenberg on 26/04/2017.
6
+//  Copyright © 2017 artal. All rights reserved.
7
+//
8
+
9
+#import <UIKit/UIKit.h>
10
+
11
+@interface RCCCustomTitleView : UIView
12
+
13
+-(instancetype)initWithFrame:(CGRect)frame subView:(UIView*)subView alignment:(NSString*)alignment;
14
+
15
+@end

+ 55
- 0
ios/RCCCustomTitleView.m View File

@@ -0,0 +1,55 @@
1
+//
2
+//  RCCTitleView.m
3
+//  ReactNativeNavigation
4
+//
5
+//  Created by Ran Greenberg on 26/04/2017.
6
+//  Copyright © 2017 artal. All rights reserved.
7
+//
8
+
9
+#import "RCCCustomTitleView.h"
10
+
11
+@interface RCCCustomTitleView ()
12
+@property (nonatomic, strong) UIView *subView;
13
+@property (nonatomic, strong) NSString *subViewAlign;
14
+@end
15
+
16
+@implementation RCCCustomTitleView
17
+
18
+
19
+-(instancetype)initWithFrame:(CGRect)frame subView:(UIView*)subView alignment:(NSString*)alignment {
20
+    self = [super initWithFrame:frame];
21
+    
22
+    if (self) {
23
+        self.backgroundColor = [UIColor clearColor];
24
+        self.subView = subView;
25
+        self.subViewAlign = alignment;
26
+        
27
+        subView.frame = self.bounds;
28
+        [self addSubview:subView];
29
+    }
30
+    
31
+    return self;
32
+}
33
+
34
+
35
+-(void)layoutSubviews {
36
+    [super layoutSubviews];
37
+    
38
+    if ([self.subViewAlign isEqualToString:@"fill"]) {
39
+        self.subView.frame = self.bounds;
40
+    }
41
+    else {
42
+        
43
+        CGFloat superViewWidth = self.superview.frame.size.width;
44
+        CGFloat paddingLeftFromCenter = (superViewWidth/2) - self.frame.origin.x;
45
+        CGFloat paddingRightFromCenter = self.frame.size.width - paddingLeftFromCenter;;
46
+        CGRect reactViewFrame = self.subView.bounds;
47
+        CGFloat minPadding = MIN(paddingLeftFromCenter, paddingRightFromCenter);
48
+        
49
+        reactViewFrame.size.width = minPadding*2;
50
+        reactViewFrame.origin.x = paddingLeftFromCenter - minPadding;
51
+        self.subView.frame = reactViewFrame;
52
+    }
53
+}
54
+
55
+@end

+ 3
- 1
ios/RCCNavigationController.m View File

@@ -96,7 +96,9 @@ NSString const *CALLBACK_ASSOCIATED_ID = @"RCCNavigationController.CALLBACK_ASSO
96 96
       [mergedStyle removeObjectForKey:@"autoAdjustScrollViewInsets"];
97 97
       [mergedStyle removeObjectForKey:@"statusBarTextColorSchemeSingleScreen"];
98 98
       [mergedStyle removeObjectForKey:@"disabledBackGesture"];
99
-      
99
+      [mergedStyle removeObjectForKey:@"navBarCustomView"];
100
+      [mergedStyle removeObjectForKey:@"navBarComponentAlignment"];
101
+       
100 102
       [mergedStyle addEntriesFromDictionary:navigatorStyle];
101 103
       navigatorStyle = mergedStyle;
102 104
     }

+ 27
- 5
ios/RCCViewController.m View File

@@ -10,6 +10,8 @@
10 10
 #import "RCCExternalViewControllerProtocol.h"
11 11
 #import "RCTHelpers.h"
12 12
 #import "RCCTitleViewHelper.h"
13
+#import "RCCCustomTitleView.h"
14
+
13 15
 
14 16
 NSString* const RCCViewControllerCancelReactTouchesNotification = @"RCCViewControllerCancelReactTouchesNotification";
15 17
 
@@ -236,7 +238,7 @@ const NSInteger TRANSPARENT_NAVBAR_TAG = 78264803;
236 238
   
237 239
   NSString *screenBackgroundColor = self.navigatorStyle[@"screenBackgroundColor"];
238 240
   if (screenBackgroundColor) {
239
-        
241
+    
240 242
     UIColor *color = screenBackgroundColor != (id)[NSNull null] ? [RCTConvert UIColor:screenBackgroundColor] : nil;
241 243
     viewController.view.backgroundColor = color;
242 244
   }
@@ -273,10 +275,10 @@ const NSInteger TRANSPARENT_NAVBAR_TAG = 78264803;
273 275
   NSMutableDictionary *rightNavButtonTextAttributes = [RCTHelpers textAttributesFromDictionary:self.navigatorStyle withPrefix:@"navBarRightButton"];
274 276
   
275 277
   if (
276
-    navButtonTextAttributes.allKeys.count > 0 ||
277
-    leftNavButtonTextAttributes.allKeys.count > 0 ||
278
-    rightNavButtonTextAttributes.allKeys.count > 0
279
-  ) {
278
+      navButtonTextAttributes.allKeys.count > 0 ||
279
+      leftNavButtonTextAttributes.allKeys.count > 0 ||
280
+      rightNavButtonTextAttributes.allKeys.count > 0
281
+      ) {
280 282
     
281 283
     for (UIBarButtonItem *item in viewController.navigationItem.leftBarButtonItems) {
282 284
       [item setTitleTextAttributes:navButtonTextAttributes forState:UIControlStateNormal];
@@ -482,8 +484,28 @@ const NSInteger TRANSPARENT_NAVBAR_TAG = 78264803;
482 484
   } else {
483 485
     self.navBarHairlineImageView.hidden = NO;
484 486
   }
487
+  
488
+  NSString *navBarCustomView = self.navigatorStyle[@"navBarCustomView"];
489
+  if (navBarCustomView && !self.navigationItem.titleView) {
490
+    if ([self.view isKindOfClass:[RCTRootView class]]) {
491
+      
492
+      RCTBridge *bridge = ((RCTRootView*)self.view).bridge;
493
+      RCTRootView *reactView = [[RCTRootView alloc] initWithBridge:bridge moduleName:navBarCustomView initialProperties:nil];
494
+      
495
+      RCCCustomTitleView *titleView = [[RCCCustomTitleView alloc] initWithFrame:self.navigationController.navigationBar.bounds subView:reactView alignment:self.navigatorStyle[@"navBarComponentAlignment"]];
496
+      titleView.backgroundColor = [UIColor clearColor];
497
+      reactView.backgroundColor = [UIColor clearColor];
498
+    
499
+      self.navigationItem.titleView = titleView;
500
+      
501
+      self.navigationItem.titleView.backgroundColor = [UIColor clearColor];
502
+      self.navigationItem.titleView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
503
+      self.navigationItem.titleView.clipsToBounds = YES;
504
+    }
505
+  }  
485 506
 }
486 507
 
508
+
487 509
 -(void)storeOriginalNavBarImages {
488 510
   
489 511
   NSMutableDictionary *originalNavBarImages = [@{} mutableCopy];

+ 13
- 7
ios/ReactNativeNavigation.xcodeproj/project.pbxproj View File

@@ -9,6 +9,7 @@
9 9
 /* Begin PBXBuildFile section */
10 10
 		260804DB1CE0D9D20094DBA1 /* RCCToolBar.m in Sources */ = {isa = PBXBuildFile; fileRef = 260804DA1CE0D9D20094DBA1 /* RCCToolBar.m */; };
11 11
 		261108801E6C495400BF5D98 /* UIViewController+Rotation.m in Sources */ = {isa = PBXBuildFile; fileRef = 2611087F1E6C495400BF5D98 /* UIViewController+Rotation.m */; };
12
+		26714EAC1EB0E9D3009F4D52 /* RCCCustomTitleView.m in Sources */ = {isa = PBXBuildFile; fileRef = 26714EAB1EB0E9D3009F4D52 /* RCCCustomTitleView.m */; };
12 13
 		26AFF3F51D7EEE2400CBA211 /* RCCTitleViewHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 26AFF3F41D7EEE2400CBA211 /* RCCTitleViewHelper.m */; };
13 14
 		CC84A19E1C1A0C4E00B3A6A2 /* RCCManager.m in Sources */ = {isa = PBXBuildFile; fileRef = CC84A1941C1A0C4E00B3A6A2 /* RCCManager.m */; };
14 15
 		CC84A19F1C1A0C4E00B3A6A2 /* RCCManagerModule.m in Sources */ = {isa = PBXBuildFile; fileRef = CC84A1961C1A0C4E00B3A6A2 /* RCCManagerModule.m */; };
@@ -53,8 +54,10 @@
53 54
 		260804DA1CE0D9D20094DBA1 /* RCCToolBar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCCToolBar.m; sourceTree = "<group>"; };
54 55
 		2611087E1E6C495400BF5D98 /* UIViewController+Rotation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIViewController+Rotation.h"; path = "../UIViewController+Rotation.h"; sourceTree = "<group>"; };
55 56
 		2611087F1E6C495400BF5D98 /* UIViewController+Rotation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UIViewController+Rotation.m"; path = "../UIViewController+Rotation.m"; sourceTree = "<group>"; };
56
-		26AFF3F31D7EEE2400CBA211 /* RCCTitleViewHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCCTitleViewHelper.h; sourceTree = "<group>"; };
57
-		26AFF3F41D7EEE2400CBA211 /* RCCTitleViewHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCCTitleViewHelper.m; sourceTree = "<group>"; };
57
+		26714EAA1EB0E9D3009F4D52 /* RCCCustomTitleView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCCCustomTitleView.h; sourceTree = "<group>"; };
58
+		26714EAB1EB0E9D3009F4D52 /* RCCCustomTitleView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCCCustomTitleView.m; sourceTree = "<group>"; };
59
+		26AFF3F31D7EEE2400CBA211 /* RCCTitleViewHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RCCTitleViewHelper.h; path = Helpers/RCCTitleViewHelper.h; sourceTree = "<group>"; };
60
+		26AFF3F41D7EEE2400CBA211 /* RCCTitleViewHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RCCTitleViewHelper.m; path = Helpers/RCCTitleViewHelper.m; sourceTree = "<group>"; };
58 61
 		CC84A1931C1A0C4E00B3A6A2 /* RCCManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCCManager.h; sourceTree = "<group>"; };
59 62
 		CC84A1941C1A0C4E00B3A6A2 /* RCCManager.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.objc; path = RCCManager.m; sourceTree = "<group>"; tabWidth = 2; };
60 63
 		CC84A1951C1A0C4E00B3A6A2 /* RCCManagerModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCCManagerModule.h; sourceTree = "<group>"; };
@@ -82,7 +85,7 @@
82 85
 		D85082C61CBCF42400FDB961 /* UIViewController+MMDrawerController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIViewController+MMDrawerController.h"; sourceTree = "<group>"; };
83 86
 		D85082C71CBCF42400FDB961 /* UIViewController+MMDrawerController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIViewController+MMDrawerController.m"; sourceTree = "<group>"; };
84 87
 		D85082C81CBCF42400FDB961 /* RCCDrawerController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RCCDrawerController.h; sourceTree = "<group>"; };
85
-		D85082CA1CBCF54200FDB961 /* RCCDrawerHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCCDrawerHelper.h; sourceTree = "<group>"; };
88
+		D85082CA1CBCF54200FDB961 /* RCCDrawerHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RCCDrawerHelper.h; path = ../RCCDrawerController/RCCDrawerHelper.h; sourceTree = "<group>"; };
86 89
 		D85082CB1CBCF54200FDB961 /* RCCDrawerHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCCDrawerHelper.m; sourceTree = "<group>"; };
87 90
 		D85082CC1CBCF54200FDB961 /* RCCDrawerProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCCDrawerProtocol.h; sourceTree = "<group>"; };
88 91
 		D85082CD1CBCF54200FDB961 /* RCCTheSideBarManagerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCCTheSideBarManagerViewController.h; sourceTree = "<group>"; };
@@ -132,9 +135,8 @@
132 135
 		D85082BB1CBCF42400FDB961 /* RCCDrawerController */ = {
133 136
 			isa = PBXGroup;
134 137
 			children = (
135
-				D85082CF1CBCF54200FDB961 /* TheSidebarController */,
136 138
 				D85082BC1CBCF42400FDB961 /* MMDrawerController */,
137
-				D85082CA1CBCF54200FDB961 /* RCCDrawerHelper.h */,
139
+				D85082CF1CBCF54200FDB961 /* TheSidebarController */,
138 140
 				D85082CB1CBCF54200FDB961 /* RCCDrawerHelper.m */,
139 141
 				D85082CC1CBCF54200FDB961 /* RCCDrawerProtocol.h */,
140 142
 				D85082CD1CBCF54200FDB961 /* RCCTheSideBarManagerViewController.h */,
@@ -202,6 +204,10 @@
202 204
 				D85082BB1CBCF42400FDB961 /* RCCDrawerController */,
203 205
 				CC84A1931C1A0C4E00B3A6A2 /* RCCManager.h */,
204 206
 				CC84A1941C1A0C4E00B3A6A2 /* RCCManager.m */,
207
+				26714EAA1EB0E9D3009F4D52 /* RCCCustomTitleView.h */,
208
+				26714EAB1EB0E9D3009F4D52 /* RCCCustomTitleView.m */,
209
+				26AFF3F31D7EEE2400CBA211 /* RCCTitleViewHelper.h */,
210
+				26AFF3F41D7EEE2400CBA211 /* RCCTitleViewHelper.m */,
205 211
 				CC84A1951C1A0C4E00B3A6A2 /* RCCManagerModule.h */,
206 212
 				CC84A1961C1A0C4E00B3A6A2 /* RCCManagerModule.m */,
207 213
 				CC84A1971C1A0C4E00B3A6A2 /* RCCNavigationController.h */,
@@ -234,8 +240,7 @@
234 240
 				2611087F1E6C495400BF5D98 /* UIViewController+Rotation.m */,
235 241
 				D8D779961D04B7180050CFEA /* RCTHelpers.h */,
236 242
 				D8D779971D04B7180050CFEA /* RCTHelpers.m */,
237
-				26AFF3F31D7EEE2400CBA211 /* RCCTitleViewHelper.h */,
238
-				26AFF3F41D7EEE2400CBA211 /* RCCTitleViewHelper.m */,
243
+				D85082CA1CBCF54200FDB961 /* RCCDrawerHelper.h */,
239 244
 			);
240 245
 			path = Helpers;
241 246
 			sourceTree = "<group>";
@@ -306,6 +311,7 @@
306 311
 				D85082E31CBCF54200FDB961 /* SidebarAirbnbAnimation.m in Sources */,
307 312
 				D84813191C8C5EB700051BAF /* RCCLightBox.m in Sources */,
308 313
 				CC84A19E1C1A0C4E00B3A6A2 /* RCCManager.m in Sources */,
314
+				26714EAC1EB0E9D3009F4D52 /* RCCCustomTitleView.m in Sources */,
309 315
 				D85082E21CBCF54200FDB961 /* RCCTheSideBarManagerViewController.m in Sources */,
310 316
 				D85082FC1CBCF8A800FDB961 /* MMDrawerBarButtonItem.m in Sources */,
311 317
 				D85083001CBCF8A800FDB961 /* UIViewController+MMDrawerController.m in Sources */,