Skip to content

Commit 00ab1a9

Browse files
author
talkol
committed
adding support for modals
1 parent 55b2fe1 commit 00ab1a9

File tree

8 files changed

+171
-53
lines changed

8 files changed

+171
-53
lines changed

.npmignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
example/
2+
example-redux/

example/src/app.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,28 +7,28 @@ import './screens/ThirdTabScreen';
77
Navigation.startTabBasedApp({
88
tabs: [
99
{
10-
title: 'One',
10+
label: 'One',
1111
screen: 'example.FirstTabScreen',
1212
icon: require('../img/one.png'),
1313
selectedIcon: require('../img/one_selected.png'),
14-
screenTitle: 'Screen One'
14+
title: 'Screen One'
1515
},
1616
{
17-
title: 'Two',
17+
label: 'Two',
1818
screen: 'example.SecondTabScreen',
1919
icon: require('../img/two.png'),
2020
selectedIcon: require('../img/two_selected.png'),
21-
screenTitle: 'Screen Two'
21+
title: 'Screen Two'
2222
},
2323
{
24-
title: 'Three',
24+
label: 'Three',
2525
screen: 'example.ThirdTabScreen',
2626
icon: require('../img/three.png'),
2727
selectedIcon: require('../img/three_selected.png'),
28-
screenTitle: 'Screen Three',
28+
title: 'Screen Three',
2929
navigatorStyle: {
30-
navBarBackgroundColor: '#26ade4',
31-
navBarTextColor: '#f0f0f0',
30+
navBarBackgroundColor: '#4dbce9',
31+
navBarTextColor: '#f7f7f7',
3232
navBarButtonColor: '#ffffff'
3333
}
3434
}

example/src/screens/FirstTabScreen.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { Navigation, Screen } from 'react-native-navigation';
1212
// need to import every screen we push
1313
import './PushedScreen';
1414
import './StyledScreen';
15+
import './ModalScreen';
1516

1617
// instead of React.Component, we extend Screen (imported above)
1718
class FirstTabScreen extends Screen {
@@ -30,6 +31,10 @@ class FirstTabScreen extends Screen {
3031
<Text style={styles.button}>Push Styled Screen</Text>
3132
</TouchableOpacity>
3233

34+
<TouchableOpacity onPress={ this.onModalPress.bind(this) }>
35+
<Text style={styles.button}>Show Modal Screen</Text>
36+
</TouchableOpacity>
37+
3338
</View>
3439
);
3540
}
@@ -41,10 +46,16 @@ class FirstTabScreen extends Screen {
4146
}
4247
onPushStyledPress() {
4348
this.navigator.push({
44-
title: "More",
49+
title: "Styled",
4550
screen: "example.StyledScreen"
4651
});
4752
}
53+
onModalPress() {
54+
this.navigator.showModal({
55+
title: "Modal",
56+
screen: "example.ModalScreen"
57+
});
58+
}
4859
}
4960

5061
const styles = StyleSheet.create({

example/src/screens/ModalScreen.js

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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);

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@
1818
"author": "Tal Kol <talkol@gmail.com>",
1919
"license": "MIT",
2020
"peerDependencies": {
21-
"react-native": ">=0.16.0"
21+
"react-native": ">=0.19.0"
2222
},
2323
"dependencies": {
24-
"react-native-controllers": "^1.1.0"
24+
"react-native-controllers": "^1.2.0"
2525
}
2626
}

src/Navigation.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,19 @@ function getRegisteredScreen(screenID) {
1717
return generator();
1818
}
1919

20+
function showModal(params = {}) {
21+
return platformSpecific.showModal(params);
22+
}
23+
24+
function dismissModal(params = {}) {
25+
return platformSpecific.dismissModal(params);
26+
}
27+
2028
export default Navigation = {
2129
registerScreen,
2230
getRegisteredScreen,
31+
showModal,
32+
dismissModal,
2333
startTabBasedApp: platformSpecific.startTabBasedApp,
2434
startSingleScreenApp: platformSpecific.startSingleScreenApp
2535
}

src/Screen.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Component } from 'react-native';
22
import platformSpecific from './platformSpecific';
3+
import Navigation from './Navigation';
34

45
class Navigator {
56
constructor(navigatorID) {
@@ -11,6 +12,12 @@ class Navigator {
1112
pop(params = {}) {
1213
return platformSpecific.navigatorPop(this, params);
1314
}
15+
showModal(params = {}) {
16+
return Navigation.showModal(params);
17+
}
18+
dismissModal(params = {}) {
19+
return Navigation.dismissModal(params);
20+
}
1421
}
1522

1623
export default class Screen extends Component {

src/platformSpecific.ios.js

Lines changed: 63 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import utils from './utils';
22
import Navigation from './Navigation';
3-
import Controllers from 'react-native-controllers';
3+
import Controllers, { Modal } from 'react-native-controllers';
44
const React = Controllers.hijackReact();
55
const {
66
ControllerRegistry,
@@ -14,32 +14,24 @@ function startTabBasedApp(params) {
1414
console.error('startTabBasedApp(params): params.tabs is required');
1515
return;
1616
}
17-
const appID = utils.getRandomId();
18-
const App = Controllers.createClass({
17+
const controllerID = utils.getRandomId();
18+
const Controller = Controllers.createClass({
1919
render: function() {
2020
return (
21-
<TabBarControllerIOS id={appID + '_tabs'}>
21+
<TabBarControllerIOS id={controllerID + '_tabs'}>
2222
{
2323
params.tabs.map(function(tab, index) {
24-
const navigatorID = appID + '_nav' + index;
24+
const navigatorID = controllerID + '_nav' + index;
2525
if (!tab.screen) {
2626
console.error('startTabBasedApp(params): every tab must include a screen property, take a look at tab#' + (index+1));
2727
return;
2828
}
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);
3830
return (
39-
<TabBarControllerIOS.Item {...tab}>
31+
<TabBarControllerIOS.Item {...tab} title={tab.label}>
4032
<NavigationControllerIOS
4133
id={navigatorID}
42-
title={tab.screenTitle}
34+
title={tab.title}
4335
component={tab.screen}
4436
passProps={{navigatorID: navigatorID}}
4537
style={navigatorStyle}
@@ -52,63 +44,60 @@ function startTabBasedApp(params) {
5244
);
5345
}
5446
});
55-
ControllerRegistry.registerController(appID, () => App);
56-
ControllerRegistry.setRootController(appID);
47+
ControllerRegistry.registerController(controllerID, () => Controller);
48+
ControllerRegistry.setRootController(controllerID);
5749
}
5850

5951
function startSingleScreenApp(params) {
6052
if (!params.screen) {
6153
console.error('startSingleScreenApp(params): params.screen is required');
6254
return;
6355
}
64-
const appID = utils.getRandomId();
65-
const App = Controllers.createClass({
56+
const controllerID = utils.getRandomId();
57+
const Controller = Controllers.createClass({
6658
render: function() {
6759
const screen = params.screen;
68-
const navigatorID = appID + '_nav';
60+
const navigatorID = controllerID + '_nav';
6961
if (!screen.screen) {
7062
console.error('startSingleScreenApp(params): screen must include a screen property');
7163
return;
7264
}
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);
8266
return (
8367
<NavigationControllerIOS
8468
id={navigatorID}
85-
title={screen.screenTitle}
69+
title={screen.title}
8670
component={screen.screen}
8771
passProps={{navigatorID: navigatorID}}
8872
style={navigatorStyle}
8973
/>
9074
);
9175
}
9276
});
93-
ControllerRegistry.registerController(appID, () => App);
94-
ControllerRegistry.setRootController(appID);
77+
ControllerRegistry.registerController(controllerID, () => Controller);
78+
ControllerRegistry.setRootController(controllerID);
9579
}
9680

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);
10483
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?');
10685
return;
10786
}
10887
const navigatorStyle = Object.assign({}, screenClass.navigatorStyle);
10988
if (params.navigatorStyle) {
11089
Object.assign(navigatorStyle, params.navigatorStyle);
11190
}
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 || {};
112101
passProps.navigatorID = navigator.navigatorID;
113102
Controllers.NavigationControllerIOS(navigator.navigatorID).push({
114103
title: params.title,
@@ -126,9 +115,41 @@ function navigatorPop(navigator, params) {
126115
});
127116
}
128117

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+
129148
export default platformSpecific = {
130149
startTabBasedApp,
131150
startSingleScreenApp,
132151
navigatorPush,
133-
navigatorPop
152+
navigatorPop,
153+
showModal,
154+
dismissModal
134155
}

0 commit comments

Comments
 (0)