Skip to content

Commit

Permalink
Merge pull request #8 from APSL/android
Browse files Browse the repository at this point in the history
Android support
  • Loading branch information
alvaromb committed Feb 18, 2016
2 parents 808418f + 3dde687 commit d967844
Show file tree
Hide file tree
Showing 8 changed files with 319 additions and 101 deletions.
9 changes: 8 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@ import NavBarBackButton from './lib/NavBarBackButton'
import NavBar from './lib/NavBar'
import NavigatorWrapper from './lib/NavigatorWrapper'
import TopNavigatorWrapper from './lib/TopNavigatorWrapper'
import { defaultRouteMapper, leftButtonRouteMapperGenerator, rightButtonRouteMapperGenerator, titleRouteMapperGenerator } from './lib/RouteMapper'
import {
defaultRouteMapper,
leftButtonRouteMapperGenerator,
rightButtonRouteMapperGenerator,
titleRouteMapperGenerator,
CenteredText
} from './lib/RouteMapper'

export {
NavBarBackButton,
Expand All @@ -13,4 +19,5 @@ export {
leftButtonRouteMapperGenerator,
rightButtonRouteMapperGenerator,
titleRouteMapperGenerator,
CenteredText,
}
34 changes: 34 additions & 0 deletions lib/NavBar.android.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React, {
Navigator,
StyleSheet,
} from 'react-native'

const stylesAndroid = StyleSheet.create({
navBar: {
backgroundColor: 'white',
}
})

class NavBar extends React.Component {
updateProgress (progress, fromIndex, toIndex) {
this._nav.updateProgress(progress, fromIndex, toIndex);
}

render () {
return (
<Navigator.NavigationBar
style={[stylesAndroid.navBar, this.props.style]}
routeMapper={this.props.routeMapper}
navState={this.props.navState}
navigator={this.props.navigator}
ref={nav => { this._nav = nav }}
/>
)
}
}

NavBar.propTypes = {
...Navigator.NavigationBar.propTypes,
}

export default NavBar
67 changes: 67 additions & 0 deletions lib/NavBarBackButton.android.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import React, { TouchableOpacity, Text, PropTypes, StyleSheet } from 'react-native'
import StyleSheetPropType from 'react-native/Libraries/StyleSheet/StyleSheetPropType'
import TextStylePropTypes from 'react-native/Libraries/Text/TextStylePropTypes'
import Ionicon from 'react-native-vector-icons/Ionicons'

class NavBarBackButton extends React.Component {
constructor (props) {
super(props)
this.state = {
tintColor: props.tintColor || 'black'
}
}

_renderBackTitle () {
if (this.props.showBackTitle) {
return (
<Text style={[this.props.style, styles.navText]}>
{this.props.children}
</Text>
)
}
}

render () {
const touchableProps = {
onPress: this.props.onPress,
onPressIn: this.props.onPressIn,
onPressOut: this.props.onPressOut,
onLongPress: this.props.onLongPress
}
return (
<TouchableOpacity
{...touchableProps}
style={styles.container}>
<Ionicon name='android-arrow-back' size={24} style={styles.icon}
color={this.state.tintColor} />
{this._renderBackTitle.bind(this)}
</TouchableOpacity>
)
}
}

NavBarBackButton.propTypes = {
...TouchableOpacity.propTypes,
tintColor: PropTypes.string,
children: PropTypes.string.isRequired,
style: StyleSheetPropType(TextStylePropTypes),
showBackTitle: PropTypes.bool,
}

const styles = StyleSheet.create({
container: {
flexDirection: 'row',
alignItems: 'center',
height: 50,
paddingRight: 15,
},
icon: {
marginLeft: 10,
},
navText: {
paddingLeft: 5,
paddingTop: 7,
},
})

export default NavBarBackButton
96 changes: 83 additions & 13 deletions lib/NavigatorWrapper.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,75 @@
import React, { View, PropTypes, Navigator } from 'react-native'
import React, {
View,
PropTypes,
Navigator,
BackAndroid,
Platform
} from 'react-native'
import NavBar from './NavBar'
import { defaultRouteMapper } from './RouteMapper'
import StyleSheetPropType from 'react-native/Libraries/StyleSheet/StyleSheetPropType'
import ViewStylePropTypes from 'react-native/Libraries/Components/View/ViewStylePropTypes'

class NavigatorWrapper extends React.Component {
static isAndroid = Platform.OS !== 'ios';

_handleAndroidBackButton () {
if (this.navigator && !this.firstComponentInStack) {
this.navigator.pop()
return true
}
return false
}

constructor (props) {
super(props)
this.navigator = undefined
this.firstComponentInStack = true
}

componentDidMount() {
// Automatically handle back button under Android platform
if (NavigatorWrapper.isAndroid && this.props.initialRoute.handleBackAndroid) {
this.bindedBackFunction = this._handleAndroidBackButton.bind(this)
BackAndroid.addEventListener('hardwareBackPress', this.bindedBackFunction)
}
}

componentWillUnmount () {
if (NavigatorWrapper.isAndroid) {
BackAndroid.removeEventListener('hardwareBackPress', this.bindedBackFunction)
}
}

renderScene (route, navigator) {
let marginTop = 64
this.firstComponentInStack = route.handleBackAndroid
if (NavigatorWrapper.isAndroid) {
// Save navigator to handle back button under Android
if (!this.navigator) {
this.navigator = navigator
}
marginTop = 56
}
const RenderComponent = route.component
return (
<View style={{flex: 1, marginTop: 64}}>
<View style={{flex: 1, marginTop: marginTop}}>
<RenderComponent
navigator={navigator}
topNavigator={this.props.topNavigator}
route={route}
{...route.passProps}
{...this.props.passProps}
{...this.props.initialRoute.passProps}
/>
</View>
)
}

render () {
const navAnimation = (NavigatorWrapper.isAndroid) ? Navigator.SceneConfigs.FadeAndroid : Navigator.SceneConfigs.PushFromRight
return (
<Navigator
initialRoute={{
component: this.props.initialComponent,
title: this.props.title || ''
}}
configureScene={(route, routeStack) => navAnimation}
initialRoute={this.props.initialRoute}
initialRouteStack={this.props.initialRouteStack}
navigationBar={
<NavBar
routeMapper={this.props.routeMapper || defaultRouteMapper()}
Expand All @@ -40,11 +83,38 @@ class NavigatorWrapper extends React.Component {
}

NavigatorWrapper.propTypes = {
initialComponent: PropTypes.func.isRequired,
title: PropTypes.string,
/**
* Provide the initial route or the initial route stack.
*
* ``leftElement``, ``textElement`` and ``rightElement``` are optional
* elements to overwrite route mapper defaults.
*/
initialRoute: PropTypes.shape({
component: PropTypes.func.isRequired,
title: PropTypes.string.isRequired,
passProps: PropTypes.object,
leftElement: PropTypes.node,
textElement: PropTypes.node,
rightElement: PropTypes.node,
handleBackAndroid: PropTypes.bool,
}),
initialRouteStack: PropTypes.arrayOf(PropTypes.object),

/**
* Optional ``topNavigator`` object to use as a parent navigator for modal
* transitions.
*/
topNavigator: PropTypes.object,
passProps: PropTypes.object,
navBarStyle: StyleSheetPropType(ViewStylePropTypes),

/**
* Optional style for the default navigation bar.
*/
navBarStyle: View.propTypes.style,

/**
* A ``routeMapper`` object to customize Left, Title and Right components for
* the ``NavigationBar``.
*/
routeMapper: PropTypes.object,
}

Expand Down
73 changes: 0 additions & 73 deletions lib/RouteMapper.ios.js

This file was deleted.

Loading

0 comments on commit d967844

Please sign in to comment.