Skip to content

Commit d967844

Browse files
committed
Merge pull request #8 from APSL/android
Android support
2 parents 808418f + 3dde687 commit d967844

File tree

8 files changed

+319
-101
lines changed

8 files changed

+319
-101
lines changed

index.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,13 @@ import NavBarBackButton from './lib/NavBarBackButton'
22
import NavBar from './lib/NavBar'
33
import NavigatorWrapper from './lib/NavigatorWrapper'
44
import TopNavigatorWrapper from './lib/TopNavigatorWrapper'
5-
import { defaultRouteMapper, leftButtonRouteMapperGenerator, rightButtonRouteMapperGenerator, titleRouteMapperGenerator } from './lib/RouteMapper'
5+
import {
6+
defaultRouteMapper,
7+
leftButtonRouteMapperGenerator,
8+
rightButtonRouteMapperGenerator,
9+
titleRouteMapperGenerator,
10+
CenteredText
11+
} from './lib/RouteMapper'
612

713
export {
814
NavBarBackButton,
@@ -13,4 +19,5 @@ export {
1319
leftButtonRouteMapperGenerator,
1420
rightButtonRouteMapperGenerator,
1521
titleRouteMapperGenerator,
22+
CenteredText,
1623
}

lib/NavBar.android.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import React, {
2+
Navigator,
3+
StyleSheet,
4+
} from 'react-native'
5+
6+
const stylesAndroid = StyleSheet.create({
7+
navBar: {
8+
backgroundColor: 'white',
9+
}
10+
})
11+
12+
class NavBar extends React.Component {
13+
updateProgress (progress, fromIndex, toIndex) {
14+
this._nav.updateProgress(progress, fromIndex, toIndex);
15+
}
16+
17+
render () {
18+
return (
19+
<Navigator.NavigationBar
20+
style={[stylesAndroid.navBar, this.props.style]}
21+
routeMapper={this.props.routeMapper}
22+
navState={this.props.navState}
23+
navigator={this.props.navigator}
24+
ref={nav => { this._nav = nav }}
25+
/>
26+
)
27+
}
28+
}
29+
30+
NavBar.propTypes = {
31+
...Navigator.NavigationBar.propTypes,
32+
}
33+
34+
export default NavBar

lib/NavBarBackButton.android.js

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import React, { TouchableOpacity, Text, PropTypes, StyleSheet } from 'react-native'
2+
import StyleSheetPropType from 'react-native/Libraries/StyleSheet/StyleSheetPropType'
3+
import TextStylePropTypes from 'react-native/Libraries/Text/TextStylePropTypes'
4+
import Ionicon from 'react-native-vector-icons/Ionicons'
5+
6+
class NavBarBackButton extends React.Component {
7+
constructor (props) {
8+
super(props)
9+
this.state = {
10+
tintColor: props.tintColor || 'black'
11+
}
12+
}
13+
14+
_renderBackTitle () {
15+
if (this.props.showBackTitle) {
16+
return (
17+
<Text style={[this.props.style, styles.navText]}>
18+
{this.props.children}
19+
</Text>
20+
)
21+
}
22+
}
23+
24+
render () {
25+
const touchableProps = {
26+
onPress: this.props.onPress,
27+
onPressIn: this.props.onPressIn,
28+
onPressOut: this.props.onPressOut,
29+
onLongPress: this.props.onLongPress
30+
}
31+
return (
32+
<TouchableOpacity
33+
{...touchableProps}
34+
style={styles.container}>
35+
<Ionicon name='android-arrow-back' size={24} style={styles.icon}
36+
color={this.state.tintColor} />
37+
{this._renderBackTitle.bind(this)}
38+
</TouchableOpacity>
39+
)
40+
}
41+
}
42+
43+
NavBarBackButton.propTypes = {
44+
...TouchableOpacity.propTypes,
45+
tintColor: PropTypes.string,
46+
children: PropTypes.string.isRequired,
47+
style: StyleSheetPropType(TextStylePropTypes),
48+
showBackTitle: PropTypes.bool,
49+
}
50+
51+
const styles = StyleSheet.create({
52+
container: {
53+
flexDirection: 'row',
54+
alignItems: 'center',
55+
height: 50,
56+
paddingRight: 15,
57+
},
58+
icon: {
59+
marginLeft: 10,
60+
},
61+
navText: {
62+
paddingLeft: 5,
63+
paddingTop: 7,
64+
},
65+
})
66+
67+
export default NavBarBackButton

lib/NavigatorWrapper.js

Lines changed: 83 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,75 @@
1-
import React, { View, PropTypes, Navigator } from 'react-native'
1+
import React, {
2+
View,
3+
PropTypes,
4+
Navigator,
5+
BackAndroid,
6+
Platform
7+
} from 'react-native'
28
import NavBar from './NavBar'
39
import { defaultRouteMapper } from './RouteMapper'
4-
import StyleSheetPropType from 'react-native/Libraries/StyleSheet/StyleSheetPropType'
5-
import ViewStylePropTypes from 'react-native/Libraries/Components/View/ViewStylePropTypes'
610

711
class NavigatorWrapper extends React.Component {
12+
static isAndroid = Platform.OS !== 'ios';
13+
14+
_handleAndroidBackButton () {
15+
if (this.navigator && !this.firstComponentInStack) {
16+
this.navigator.pop()
17+
return true
18+
}
19+
return false
20+
}
21+
22+
constructor (props) {
23+
super(props)
24+
this.navigator = undefined
25+
this.firstComponentInStack = true
26+
}
27+
28+
componentDidMount() {
29+
// Automatically handle back button under Android platform
30+
if (NavigatorWrapper.isAndroid && this.props.initialRoute.handleBackAndroid) {
31+
this.bindedBackFunction = this._handleAndroidBackButton.bind(this)
32+
BackAndroid.addEventListener('hardwareBackPress', this.bindedBackFunction)
33+
}
34+
}
35+
36+
componentWillUnmount () {
37+
if (NavigatorWrapper.isAndroid) {
38+
BackAndroid.removeEventListener('hardwareBackPress', this.bindedBackFunction)
39+
}
40+
}
41+
842
renderScene (route, navigator) {
43+
let marginTop = 64
44+
this.firstComponentInStack = route.handleBackAndroid
45+
if (NavigatorWrapper.isAndroid) {
46+
// Save navigator to handle back button under Android
47+
if (!this.navigator) {
48+
this.navigator = navigator
49+
}
50+
marginTop = 56
51+
}
952
const RenderComponent = route.component
1053
return (
11-
<View style={{flex: 1, marginTop: 64}}>
54+
<View style={{flex: 1, marginTop: marginTop}}>
1255
<RenderComponent
1356
navigator={navigator}
1457
topNavigator={this.props.topNavigator}
1558
route={route}
1659
{...route.passProps}
17-
{...this.props.passProps}
60+
{...this.props.initialRoute.passProps}
1861
/>
1962
</View>
2063
)
2164
}
2265

2366
render () {
67+
const navAnimation = (NavigatorWrapper.isAndroid) ? Navigator.SceneConfigs.FadeAndroid : Navigator.SceneConfigs.PushFromRight
2468
return (
2569
<Navigator
26-
initialRoute={{
27-
component: this.props.initialComponent,
28-
title: this.props.title || ''
29-
}}
70+
configureScene={(route, routeStack) => navAnimation}
71+
initialRoute={this.props.initialRoute}
72+
initialRouteStack={this.props.initialRouteStack}
3073
navigationBar={
3174
<NavBar
3275
routeMapper={this.props.routeMapper || defaultRouteMapper()}
@@ -40,11 +83,38 @@ class NavigatorWrapper extends React.Component {
4083
}
4184

4285
NavigatorWrapper.propTypes = {
43-
initialComponent: PropTypes.func.isRequired,
44-
title: PropTypes.string,
86+
/**
87+
* Provide the initial route or the initial route stack.
88+
*
89+
* ``leftElement``, ``textElement`` and ``rightElement``` are optional
90+
* elements to overwrite route mapper defaults.
91+
*/
92+
initialRoute: PropTypes.shape({
93+
component: PropTypes.func.isRequired,
94+
title: PropTypes.string.isRequired,
95+
passProps: PropTypes.object,
96+
leftElement: PropTypes.node,
97+
textElement: PropTypes.node,
98+
rightElement: PropTypes.node,
99+
handleBackAndroid: PropTypes.bool,
100+
}),
101+
initialRouteStack: PropTypes.arrayOf(PropTypes.object),
102+
103+
/**
104+
* Optional ``topNavigator`` object to use as a parent navigator for modal
105+
* transitions.
106+
*/
45107
topNavigator: PropTypes.object,
46-
passProps: PropTypes.object,
47-
navBarStyle: StyleSheetPropType(ViewStylePropTypes),
108+
109+
/**
110+
* Optional style for the default navigation bar.
111+
*/
112+
navBarStyle: View.propTypes.style,
113+
114+
/**
115+
* A ``routeMapper`` object to customize Left, Title and Right components for
116+
* the ``NavigationBar``.
117+
*/
48118
routeMapper: PropTypes.object,
49119
}
50120

lib/RouteMapper.ios.js

Lines changed: 0 additions & 73 deletions
This file was deleted.

0 commit comments

Comments
 (0)