At this stage, our RN practice is based on the published app, such as replacing a sub-module that enters from a portal into an RN page. Then we can design this submodule as a generic RN container, and all RN pages jump inside the RN container.
RN container in iOS using Uiviewcontroller, Android using activity or fragment, load bundle files, normally, a module only one bundle file.
To achieve the page jump, we can use the Navigator component, the specific use can refer to: http://blog.csdn.net/codetomylaw/article/details/52059493
There are several issues that need to be addressed:
1. Navigation bar
The navigation bar in the native app is usually managed uniformly, so in a generic container, we can define a generic RN navigation.
2. Native Jump RN Container
Use normal native jump mode, such as StartActivity in Android.
3, RN container return native interface
Because the navigation bar is already written in the RN interface, then the native end needs to provide a bridging method to the RN call, the bridge method needs to implement the logic: finish off the initialized RN container
4. Handling Android Return key
See Demo code for details
OK, let's demonstrate it through a simple demo.
The effect we achieve is
1, from the native page to jump RN page A,rn page A is loaded by the RN container, click on the upper left corner to return to the native interface
2, click on the RN page a "Jump details" can jump to the RN page B
3, click on the RN page B in the upper left corner or the Android physical return key, you can return to the RN page a
4, click on the top left corner of the RN page B or the Android physical return key, you can block the return of the page, to achieve our own logic
5. Click Share in Rn page B to invoke the callback
Page A is shown below:
Page B is shown below:
The navigation component code is as follows: Nav.js
import React, {Component} from 'react';
import {
StyleSheet,
View,
Text,
Image,
TouchableOpacity,
Platform,
NativeModules,
} from 'react-native';
const {CommonDispatcher} = NativeModules;
// Universal navigation components
export default class Nav extends Component {
constructor (props) {
super (props);
height = (Platform.OS === 'ios')? 64: 45;
leftWidth = 60;
rightWidth = 60;
}
// Control the return event, navigator returns or returns to the native page
back () {
const {navigator} = this.props;
if (navigator) {
const routers = navigator.getCurrentRoutes ();
if (routers.length> 1) {
navigator.pop ();
} else {
// Here is the bridge, you need to finish off the RN shell and jump to the native page
CommonDispatcher.toBack ((});
}
}
}
// Top left corner event
leftCallBack () {
if (this.props.leftCallBack) {
this.props.leftCallBack ();
} else {
this.back ();
}
}
// Top right corner event
rightCallBack () {
if (this.props.rightCallBack) {
this.props.rightCallBack ();
}
}
render () {
// The return picture on the left can be hidden
let leftView = this.props.hiddenBack?
<View style = {styles.leftView} />
:(
<TouchableOpacity onPress = (this.leftCallBack.bind (this)}>
<View style = {styles.leftView}>
<Image source = {{uri: "nav_back"}} style = {styles.image} />
</ View>
</ TouchableOpacity>);
// The title now only supports text, and the style can also be modified later
let centerView = <Text style = {styles.title}> {this.props.title} </ Text>;
// The upper right corner area currently only supports text, and subsequent pictures or graphics can be supported
let rightView = (
<TouchableOpacity onPress = {this.rightCallBack.bind (this)}>
<Text style = {styles.rightTitle}> {this.props.rightTitle} </ Text>
</ TouchableOpacity>);
return (
<View style = {styles.container} height = {height} backgroundColor = {this.props.backgroundColor}>
<View style = {styles.leftView} width = {leftWidth}> {leftView} </ View>
<View style = {styles.centerView}> {centerView} </ View>
<View style = {styles.rightView} width = {rightWidth}> {rightView} </ View>
</ View>
);
}
}
const styles = StyleSheet.create ({
container: {
justifyContent: 'space-between',
flexDirection: 'row',
alignItems: 'center',
paddingTop: (Platform.OS === 'ios')? 20: 0,
},
leftView: {
flexDirection: 'row',
alignItems: 'center',
},
rightView: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'flex-end',
},
centerView: {
flex: 1,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
},
image: {
marginLeft: 20,
width: 15,
height: 15,
},
title: {
fontSize: 17,
color: '# ffffff',
},
rightTitle: {
marginRight: 15,
color: 'white'
},
});
The container component code is as follows (Homepage is RN page a): Page.js
'use strict';
import React, {Component} from 'react';
import {
Platform,
Navigator,
BackAndroid,
NativeModules,
View,
Text,
AppRegistry,
TouchableOpacity,
} from 'react-native';
import Nav from './Nav.js';
import DetailPage from './DetailPage';
const {CommonDispatcher} = NativeModules;
export default class PageIndex extends Component {
constructor (props) {
super (props);
}
componentWillMount () {
if (Platform.OS === 'android') {
// Listen to Android physical keys to return
BackAndroid.addEventListener ('hardwareBackPress', this.onBackAndroid);
}
}
componentWillUnmount () {
if (Platform.OS === 'android') {
BackAndroid.removeEventListener ('hardwareBackPress', this.onBackAndroid);
}
}
// Handle Android physical back key
onBackAndroid = () => {
let nav = this.navigator;
let routers = nav.getCurrentRoutes ();
// Handle when the current page is not a root page
if (routers.length> 1) {
let top = routers [routers.length-1];
let handleBack = top.handleBack;
if (handleBack) {
// The route or component decides that this interface handles the back key by itself
handleBack ();
return true;
}
// default processing
nav.pop ();
return true;
}
return false;
};
render () {
return (
<Navigator
ref = {nav => {this.navigator = nav;}}
initialRoute = {{name: "HomePage", component: HomePage}}
configureScene = {(route) => {
return Navigator.SceneConfigs.PushFromRight;
}}
renderScene = {(route, navigator) => {
let Component = route.component;
return <Component {... route.params} navigator = {navigator} />
}} />
);
}
}
// This is a test page using universal navigation
class HomePage extends Component {
toDetailPage () {
const {navigator} = this.props;
if (navigator) {
navigator.push ({
name: 'DetailPage',
component: DetailPage,
params: {
rightTitle: "Share"
}
})
}
}
render () {
return (
<View style = ({flex: 1}}>
<Nav {... this.props} ref = 'nav' title = 'General Navigation Home' backgroundColor = '# e6454a' />
<TouchableOpacity onPress = {this.toDetailPage.bind (this)} style = ({backgroundColor: '# f2f2f2', marginTop: 20, justifyContent: 'center', alignItems: 'center',)}>
<Text style = {{fontSize: 28, color: '# 998462', textAlign: 'center',}}> jump details </ Text>
</ TouchableOpacity>
</ View>
);
}
}
AppRegistry.registerComponent ('Your own module name', () => PageIndex);
RN page b code is as follows: Detailpage.js
'use strict';
import React, {Component} from 'react';
import {
View,
Text,
} from 'react-native';
import Nav from './Nav.js';
export default class DetailPage extends Component {
constructor (props) {
super (props);
let navigator = this.props.navigator;
if (navigator) {
let routes = navigator.getCurrentRoutes (); // nav is the navigator object
let lastRoute = routes [routes.length-1]; // route object corresponding to the current page
lastRoute.handleBack = this.leftCallBack.bind (this); // Set the hanleBack property of the route object
}
}
/ **
* Scenario: Edit page, click Physics or top left corner to return, you need to prompt "Are you sure you want to abandon the modification."
* /
leftCallBack () {
let logic = false; // You can modify it to true
if (logic) {
alert ("I don't want to return");
} else {
this.refs.nav.back ();
}
}
render () {
return (
<View style = ({flex: 1}}>
<Nav {... this.props} ref = 'nav' leftCallBack = {this.leftCallBack.bind (this)} rightCallBack = (() => {alert ('Share'))} title = 'General Navigation Detail' backgroundColor = '# e6454a' />
<View style = ({flex: 1, backgroundColor: '# f2f2f2', justifyContent: 'center', alignItems: 'center',)}>
<Text style = {(fontSize: 28, color: '# 998462', textAlign: 'center',)}> I am just an RN page in the container </ Text>
</ View>
</ View>
);
}
}
Well, this basically implements the generic RN container and navigation, and of course there are some areas that can be optimized.