"React-native series" 43, general container and navigation design scheme

Source: Internet
Author: User
Tags bind constructor


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.


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.