Sfoglia il codice sorgente

adding support for modals

talkol 8 anni fa
parent
commit
00ab1a9974

+ 1
- 0
.npmignore Vedi File

@@ -1 +1,2 @@
1 1
 example/
2
+example-redux/

+ 8
- 8
example/src/app.js Vedi File

@@ -7,28 +7,28 @@ import './screens/ThirdTabScreen';
7 7
 Navigation.startTabBasedApp({
8 8
   tabs: [
9 9
     {
10
-      title: 'One',
10
+      label: 'One',
11 11
       screen: 'example.FirstTabScreen',
12 12
       icon: require('../img/one.png'),
13 13
       selectedIcon: require('../img/one_selected.png'),
14
-      screenTitle: 'Screen One'
14
+      title: 'Screen One'
15 15
     },
16 16
     {
17
-      title: 'Two',
17
+      label: 'Two',
18 18
       screen: 'example.SecondTabScreen',
19 19
       icon: require('../img/two.png'),
20 20
       selectedIcon: require('../img/two_selected.png'),
21
-      screenTitle: 'Screen Two'
21
+      title: 'Screen Two'
22 22
     },
23 23
     {
24
-      title: 'Three',
24
+      label: 'Three',
25 25
       screen: 'example.ThirdTabScreen',
26 26
       icon: require('../img/three.png'),
27 27
       selectedIcon: require('../img/three_selected.png'),
28
-      screenTitle: 'Screen Three',
28
+      title: 'Screen Three',
29 29
       navigatorStyle: {
30
-        navBarBackgroundColor: '#26ade4',
31
-        navBarTextColor: '#f0f0f0',
30
+        navBarBackgroundColor: '#4dbce9',
31
+        navBarTextColor: '#f7f7f7',
32 32
         navBarButtonColor: '#ffffff'
33 33
       }
34 34
     }

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

@@ -12,6 +12,7 @@ import { Navigation, Screen } from 'react-native-navigation';
12 12
 // need to import every screen we push
13 13
 import './PushedScreen';
14 14
 import './StyledScreen';
15
+import './ModalScreen';
15 16
 
16 17
 // instead of React.Component, we extend Screen (imported above)
17 18
 class FirstTabScreen extends Screen {
@@ -30,6 +31,10 @@ class FirstTabScreen extends Screen {
30 31
           <Text style={styles.button}>Push Styled Screen</Text>
31 32
         </TouchableOpacity>
32 33
 
34
+        <TouchableOpacity onPress={ this.onModalPress.bind(this) }>
35
+          <Text style={styles.button}>Show Modal Screen</Text>
36
+        </TouchableOpacity>
37
+
33 38
       </View>
34 39
     );
35 40
   }
@@ -41,10 +46,16 @@ class FirstTabScreen extends Screen {
41 46
   }
42 47
   onPushStyledPress() {
43 48
     this.navigator.push({
44
-      title: "More",
49
+      title: "Styled",
45 50
       screen: "example.StyledScreen"
46 51
     });
47 52
   }
53
+  onModalPress() {
54
+    this.navigator.showModal({
55
+      title: "Modal",
56
+      screen: "example.ModalScreen"
57
+    });
58
+  }
48 59
 }
49 60
 
50 61
 const styles = StyleSheet.create({

+ 68
- 0
example/src/screens/ModalScreen.js Vedi File

@@ -0,0 +1,68 @@
1
+import React, {
2
+  Text,
3
+  View,
4
+  ScrollView,
5
+  TouchableOpacity,
6
+  StyleSheet
7
+} from 'react-native';
8
+
9
+// important imports, the magic is here
10
+import { Navigation, Screen } from 'react-native-navigation';
11
+
12
+// need to import every screen we push
13
+import './PushedScreen';
14
+import './StyledScreen';
15
+
16
+// instead of React.Component, we extend Screen (imported above)
17
+class ModalScreen extends Screen {
18
+  constructor(props) {
19
+    super(props);
20
+  }
21
+  render() {
22
+    return (
23
+      <View style={{flex: 1, padding: 20}}>
24
+
25
+        <TouchableOpacity onPress={ this.onPushPress.bind(this) }>
26
+          <Text style={styles.button}>Push Plain Screen</Text>
27
+        </TouchableOpacity>
28
+
29
+        <TouchableOpacity onPress={ this.onPushStyledPress.bind(this) }>
30
+          <Text style={styles.button}>Push Styled Screen</Text>
31
+        </TouchableOpacity>
32
+
33
+        <TouchableOpacity onPress={ this.onClosePress.bind(this) }>
34
+          <Text style={styles.button}>Close Modal</Text>
35
+        </TouchableOpacity>
36
+
37
+      </View>
38
+    );
39
+  }
40
+  onPushPress() {
41
+    this.navigator.push({
42
+      title: "More",
43
+      screen: "example.PushedScreen"
44
+    });
45
+  }
46
+  onPushStyledPress() {
47
+    this.navigator.push({
48
+      title: "More",
49
+      screen: "example.StyledScreen"
50
+    });
51
+  }
52
+  onClosePress() {
53
+    this.navigator.dismissModal();
54
+  }
55
+}
56
+
57
+const styles = StyleSheet.create({
58
+  button: {
59
+    textAlign: 'center',
60
+    fontSize: 18,
61
+    marginBottom: 10,
62
+    marginTop:10,
63
+    color: 'blue'
64
+  }
65
+});
66
+
67
+// every screen must be registered with a unique name
68
+Navigation.registerScreen('example.ModalScreen', () => ModalScreen);

+ 2
- 2
package.json Vedi File

@@ -18,9 +18,9 @@
18 18
   "author": "Tal Kol <talkol@gmail.com>",
19 19
   "license": "MIT",
20 20
   "peerDependencies": {
21
-    "react-native": ">=0.16.0"
21
+    "react-native": ">=0.19.0"
22 22
   },
23 23
   "dependencies": {
24
-    "react-native-controllers": "^1.1.0"
24
+    "react-native-controllers": "^1.2.0"
25 25
   }
26 26
 }

+ 10
- 0
src/Navigation.js Vedi File

@@ -17,9 +17,19 @@ function getRegisteredScreen(screenID) {
17 17
   return generator();
18 18
 }
19 19
 
20
+function showModal(params = {}) {
21
+  return platformSpecific.showModal(params);
22
+}
23
+
24
+function dismissModal(params = {}) {
25
+  return platformSpecific.dismissModal(params);
26
+}
27
+
20 28
 export default Navigation = {
21 29
   registerScreen,
22 30
   getRegisteredScreen,
31
+  showModal,
32
+  dismissModal,
23 33
   startTabBasedApp: platformSpecific.startTabBasedApp,
24 34
   startSingleScreenApp: platformSpecific.startSingleScreenApp
25 35
 }

+ 7
- 0
src/Screen.js Vedi File

@@ -1,5 +1,6 @@
1 1
 import { Component } from 'react-native';
2 2
 import platformSpecific from './platformSpecific';
3
+import Navigation from './Navigation';
3 4
 
4 5
 class Navigator {
5 6
   constructor(navigatorID) {
@@ -11,6 +12,12 @@ class Navigator {
11 12
   pop(params = {}) {
12 13
     return platformSpecific.navigatorPop(this, params);
13 14
   }
15
+  showModal(params = {}) {
16
+    return Navigation.showModal(params);
17
+  }
18
+  dismissModal(params = {}) {
19
+    return Navigation.dismissModal(params);
20
+  }
14 21
 }
15 22
 
16 23
 export default class Screen extends Component {

+ 63
- 42
src/platformSpecific.ios.js Vedi File

@@ -1,6 +1,6 @@
1 1
 import utils from './utils';
2 2
 import Navigation from './Navigation';
3
-import Controllers from 'react-native-controllers';
3
+import Controllers, { Modal } from 'react-native-controllers';
4 4
 const React = Controllers.hijackReact();
5 5
 const {
6 6
   ControllerRegistry,
@@ -14,32 +14,24 @@ function startTabBasedApp(params) {
14 14
     console.error('startTabBasedApp(params): params.tabs is required');
15 15
     return;
16 16
   }
17
-  const appID = utils.getRandomId();
18
-  const App = Controllers.createClass({
17
+  const controllerID = utils.getRandomId();
18
+  const Controller = Controllers.createClass({
19 19
     render: function() {
20 20
       return (
21
-        <TabBarControllerIOS id={appID + '_tabs'}>
21
+        <TabBarControllerIOS id={controllerID + '_tabs'}>
22 22
         {
23 23
           params.tabs.map(function(tab, index) {
24
-            const navigatorID = appID + '_nav' + index;
24
+            const navigatorID = controllerID + '_nav' + index;
25 25
             if (!tab.screen) {
26 26
               console.error('startTabBasedApp(params): every tab must include a screen property, take a look at tab#' + (index+1));
27 27
               return;
28 28
             }
29
-            const screenClass = Navigation.getRegisteredScreen(tab.screen);
30
-            if (!screenClass) {
31
-              console.error('Cannot create screen ' + tab.screen + '. Are you it was registered with Navigation.registerScreen?');
32
-              return;
33
-            }
34
-            const navigatorStyle = Object.assign({}, screenClass.navigatorStyle);
35
-            if (tab.navigatorStyle) {
36
-              Object.assign(navigatorStyle, tab.navigatorStyle);
37
-            }
29
+            const { navigatorStyle } = _mergeScreenSpecificSettings(tab.screen, tab);
38 30
             return (
39
-              <TabBarControllerIOS.Item {...tab}>
31
+              <TabBarControllerIOS.Item {...tab} title={tab.label}>
40 32
                 <NavigationControllerIOS
41 33
                   id={navigatorID}
42
-                  title={tab.screenTitle}
34
+                  title={tab.title}
43 35
                   component={tab.screen}
44 36
                   passProps={{navigatorID: navigatorID}}
45 37
                   style={navigatorStyle}
@@ -52,8 +44,8 @@ function startTabBasedApp(params) {
52 44
       );
53 45
     }
54 46
   });
55
-  ControllerRegistry.registerController(appID, () => App);
56
-  ControllerRegistry.setRootController(appID);
47
+  ControllerRegistry.registerController(controllerID, () => Controller);
48
+  ControllerRegistry.setRootController(controllerID);
57 49
 }
58 50
 
59 51
 function startSingleScreenApp(params) {
@@ -61,28 +53,20 @@ function startSingleScreenApp(params) {
61 53
     console.error('startSingleScreenApp(params): params.screen is required');
62 54
     return;
63 55
   }
64
-  const appID = utils.getRandomId();
65
-  const App = Controllers.createClass({
56
+  const controllerID = utils.getRandomId();
57
+  const Controller = Controllers.createClass({
66 58
     render: function() {
67 59
       const screen = params.screen;
68
-      const navigatorID = appID + '_nav';
60
+      const navigatorID = controllerID + '_nav';
69 61
       if (!screen.screen) {
70 62
         console.error('startSingleScreenApp(params): screen must include a screen property');
71 63
         return;
72 64
       }
73
-      const screenClass = Navigation.getRegisteredScreen(screen.screen);
74
-      if (!screenClass) {
75
-        console.error('Cannot create screen ' + screen.screen + '. Are you it was registered with Navigation.registerScreen?');
76
-        return;
77
-      }
78
-      const navigatorStyle = Object.assign({}, screenClass.navigatorStyle);
79
-      if (screen.navigatorStyle) {
80
-        Object.assign(navigatorStyle, screen.navigatorStyle);
81
-      }
65
+      const { navigatorStyle } = _mergeScreenSpecificSettings(screen.screen, screen);
82 66
       return (
83 67
         <NavigationControllerIOS
84 68
           id={navigatorID}
85
-          title={screen.screenTitle}
69
+          title={screen.title}
86 70
           component={screen.screen}
87 71
           passProps={{navigatorID: navigatorID}}
88 72
           style={navigatorStyle}
@@ -90,25 +74,30 @@ function startSingleScreenApp(params) {
90 74
       );
91 75
     }
92 76
   });
93
-  ControllerRegistry.registerController(appID, () => App);
94
-  ControllerRegistry.setRootController(appID);
77
+  ControllerRegistry.registerController(controllerID, () => Controller);
78
+  ControllerRegistry.setRootController(controllerID);
95 79
 }
96 80
 
97
-function navigatorPush(navigator, params) {
98
-  if (!params.screen) {
99
-    console.error('Navigator.push(params): params.screen is required');
100
-    return;
101
-  }
102
-  const passProps = params.passProps || {};
103
-  const screenClass = Navigation.getRegisteredScreen(params.screen);
81
+function _mergeScreenSpecificSettings(screenID, params) {
82
+  const screenClass = Navigation.getRegisteredScreen(screenID);
104 83
   if (!screenClass) {
105
-    console.error('Cannot create screen ' + params.screen + '. Are you it was registered with Navigation.registerScreen?');
84
+    console.error('Cannot create screen ' + screenID + '. Are you it was registered with Navigation.registerScreen?');
106 85
     return;
107 86
   }
108 87
   const navigatorStyle = Object.assign({}, screenClass.navigatorStyle);
109 88
   if (params.navigatorStyle) {
110 89
     Object.assign(navigatorStyle, params.navigatorStyle);
111 90
   }
91
+  return { navigatorStyle };
92
+}
93
+
94
+function navigatorPush(navigator, params) {
95
+  if (!params.screen) {
96
+    console.error('Navigator.push(params): params.screen is required');
97
+    return;
98
+  }
99
+  const { navigatorStyle } = _mergeScreenSpecificSettings(params.screen, params);
100
+  const passProps = params.passProps || {};
112 101
   passProps.navigatorID = navigator.navigatorID;
113 102
   Controllers.NavigationControllerIOS(navigator.navigatorID).push({
114 103
     title: params.title,
@@ -126,9 +115,41 @@ function navigatorPop(navigator, params) {
126 115
   });
127 116
 }
128 117
 
118
+function showModal(params) {
119
+  if (!params.screen) {
120
+    console.error('showModal(params): params.screen is required');
121
+    return;
122
+  }
123
+  const { navigatorStyle } = _mergeScreenSpecificSettings(params.screen, params);
124
+  const controllerID = utils.getRandomId();
125
+  const Controller = Controllers.createClass({
126
+    render: function() {
127
+      const navigatorID = controllerID + '_nav';
128
+      const { navigatorStyle } = _mergeScreenSpecificSettings(params.screen, params);
129
+      return (
130
+        <NavigationControllerIOS
131
+          id={navigatorID}
132
+          title={params.title}
133
+          component={params.screen}
134
+          passProps={{navigatorID: navigatorID}}
135
+          style={navigatorStyle}
136
+        />
137
+      );
138
+    }
139
+  });
140
+  ControllerRegistry.registerController(controllerID, () => Controller);
141
+  Modal.showController(controllerID, params.animationType);
142
+}
143
+
144
+function dismissModal(params) {
145
+  Modal.dismissController(params.animationType);
146
+}
147
+
129 148
 export default platformSpecific = {
130 149
   startTabBasedApp,
131 150
   startSingleScreenApp,
132 151
   navigatorPush,
133
-  navigatorPop
152
+  navigatorPop,
153
+  showModal,
154
+  dismissModal
134 155
 }