基础篇章:关于 React Native 之 Navigator 组件的讲解

综合 来源:smart_android 143℃ 0评论

 


(友情提示:RN学习,从最基础的开始,大家不要嫌弃太基础,会的同学请自行略过,希望不要耽误已经会的同学的宝贵时间)

 

今天我们来讲讲Navigator这个小家伙,呃……不能说小家伙,因为它还是很厉害的,有了它我就就能实现各个界面的跳转和切换。所以它的名字叫导航器。来,今天我们就一起来学习学习它。

使用我Navigator可以让你们实现在应用内不同页面的切换,我是用JavaScript实现的,而且我有两个:IOS和Android,如果在IOS上使用请用我的双胞胎兄弟NavigatorIOS,因为它充分利用本地的UIKit导航。

要想设置Navigator,使用我,你们必须确定一个或多个调用routes对象,去定义每个场景。你们还可以利用renderScene方法,导航栏可以根据指定的路由来渲染场景。

官网基础小例子

render() {
 const routes = [
   {title: 'First Scene', index: 0},
   {title: 'Second Scene', index: 1},
 ];
 return (
   <Navigator
     initialRoute={routes[0]}
     initialRouteStack={routes}
     renderScene={(route, navigator) =>
       <TouchableHighlight onPress={() => {
         if (route.index === 0) {
           navigator.push(routes[1]);
         } else {
           navigator.pop();
         }
       }}>
       <Text>Hello {route.title}!</Text>
       </TouchableHighlight>
     }
     style={{padding: 100}}
   />
 );
}

nitialRoute
在上面的示例中,initialRoute 用于指定的第一个路由。它包含一个标题属性,标识路由。RenderScene 属性返回一个函数,显示路由标题文本。
initialRouteStack
initialRoute指定第一个显示的页面,而要设置多个场景,你们通过initialRouteStack属性了。通过上面例子,我们可以看到定义了两个路由,而且每个路由都有一个用于管理被渲染场景的索引属性。在renderScene方法中有一个触摸事件,触摸决定导航器是推或者弹出哪个导航场景。

Navigation Bar

我们可以在Navigator上设置标题导航栏Navigation Bar,在标题导航栏中我们可以通过routeMapper属性去设置左,右和标题导航栏。在配置左,右,和标题导航栏项目,您可以访问信息,如当前路由对象和导航状态。这使您可以为每个场景自定义标题以及按钮。例如,您可以选择隐藏场景中的左键。
例子如下:

<Navigator
 renderScene={(route, navigator) =>
   // ...
 }
 navigationBar={
    <Navigator.NavigationBar
      routeMapper={{
        LeftButton: (route, navigator, index, navState) =>
         { return (Cancel); },
        RightButton: (route, navigator, index, navState) =>
          { return (Done); },
        Title: (route, navigator, index, navState) =>
          { return (Awesome Nav Bar); },
      }}
      style={{backgroundColor: 'gray'}}
    />
 }
/>

场景转换

要想改变场景的动画和转换,相当于我们Android中的进场和转场动画,我们可以通过configureScene属性来获得对于给定路线的配置对象。如下:

<Navigator
 renderScene={(route, navigator) =>
   // ...
 }
 configureScene={(route, routeStack) =>
   Navigator.SceneConfigs.FloatFromBottom}
/>

属性

  • configureScene function 就是通过它配置场景转换的。它有如下属性:

    • Navigator.SceneConfigs.PushFromRight (default)

    • Navigator.SceneConfigs.FloatFromRight

    • Navigator.SceneConfigs.FloatFromLeft

    • Navigator.SceneConfigs.FloatFromBottom

    • Navigator.SceneConfigs.FloatFromBottomAndroid

    • Navigator.SceneConfigs.FadeAndroid

    • Navigator.SceneConfigs.HorizontalSwipeJump

    • Navigator.SceneConfigs.HorizontalSwipeJumpFromRight

    • Navigator.SceneConfigs.VerticalUpSwipeJump

    • Navigator.SceneConfigs.VerticalDownSwipeJump

  • initialRoute object 定义启动时加载的路由。路由是导航栏用来识别渲染场景的一个对象。initialRoute必须是initialRouteStack中的一个路由。initialRoute默认为initialRouteStack中最后一项。

  • initialRouteStack [object] 存放路由的一个数组

  • navigationBar node 上面介绍了

  • navigator object

  • onDidFocus function 每当导航切换完成或初始化之后,调用此回调,参数为新场景的路由

  • onWillFocus function 会在导航切换之前调用,参数为目标路由

  • renderScene function 用来渲染每一个路由指定的页面

  • sceneStyle 样式风格

方法

  • immediatelyResetRouteStack(nextRouteStack) 用新的路由数组来重置路由栈

  • jumpTo(route) 跳转到传入的已有的场景并且不卸载

  • jumpForward(0) 跳转到下一个场景

  • jumpBack(0) 同上相反的意思

  • push(route) 跳转到新的场景,并且将场景入栈,你可以稍后用jump forward 跳转回去

  • popN(n) 回到ñ场景一次。当N = 1,行为相匹配pop()方法。当N是无效的(负或大于当前的路线计算),什么也不做。

  • pop(0) 跳转回去并且卸载掉当前场景

  • replaceAtIndex(route, index, cb) 替换掉指定序列的路由场景

  • replace(route) 用一个新路由替换当前场景

  • replacePrevious(route) 替换掉之前的场景

  • popToTop(0) pop到栈中的第一个场景,卸载掉所有的其他场景

  • popToRoute(route) pop到路由指定的场景,在整个路由栈中,处于指定场景之后的场景将会被卸载

  • replacePreviousAndPop(route) 取代之前的场景,并弹出它

  • resetTo(route) 跳转到指定的新场景,并重置路由栈

  • getCurrentRoutes() 获取当前栈里的路由

实例

效果图


怎么样?我的样子很帅吧,是不是很想和我玩,那就赶紧行动起来吧,我已经迫不及待的想跟你们一起玩了。来看看怎么和我玩的实例代码吧。

代码

import React, { Component } from 'react';
import {
 AppRegistry,
 StyleSheet,
 Text,
 Navigator,
 Image,
 TouchableHighlight,
 TouchableOpacity,
 View
} from 'react-native';

NavigationBarRouteMapper = {
  LeftButton(route, navigator, index, navState) {
    if (route.id === 'first') {
      return null;
    }
    previousRoute = navState.routeStack[index - 1];
    return (
      <TouchableOpacity
        onPress={() => navigator.pop()}
        style={styles.navBarLeftButton}>
        <Image source={require('./back.png')} style={styles.backImage}>
        </Image>
      </TouchableOpacity>
    );
  },
  RightButton(route, navigator, index, navState) {
    if (route.id === 'second') {
      return null;
    }
    return (
      <TouchableOpacity
        onPress={() => navigator.push({id:'second',title:'第二页',data:"我是从第一页跳转过来的"})}
        style={styles.navBarRightButton}>
        <Text style={[styles.navBarButtonText]}>
          下一页
        </Text>
      </TouchableOpacity>
    );
  },

  Title(route, navigator, index, navState) {
    return (
      <Text style={[styles.navBarTitleText]}>
        {route.title}
      </Text>
    );
  },
};

export default class NavigatorDemo extends Component {
  render(){
     return (
       <Navigator
         style = {styles.container}
         initialRoute={{id:"first",title:"第一页"}}
         renderScene={this.renderNav}
         configureScene={(route, routeStack) => Navigator.SceneConfigs.HorizontalSwipeJump}
         navigationBar={
           <Navigator.NavigationBar
             routeMapper={NavigationBarRouteMapper}
             style={{backgroundColor:'white'}}
          />
         }
         />
     );
   }

   renderNav(route,nav){
       switch (route.id) {
         case 'first':
           return <FirstScreen navigator={nav} title="第一页"/ >;
         case 'second':
           return (<SecondScreen navigator={nav} title="第二页" data={route.data}/>);
       }
   }
}

class FirstScreen extends Component{
  toSecond=()=>{
    this.props.navigator.push({id:"second",title:"第二页",data:"我是第二页"});
 }
  render(){
    return (
      <View style={styles.firstView}>
        <TouchableHighlight
         style={{padding:10}}
         onPress={this.toSecond}
         underlayColor="blue">
           <Text style={styles.contentText}>第一页</Text>
        </TouchableHighlight>
      </View>
    );
  }
}

class SecondScreen extends Component{
  toFirst=()=>{
    this.props.navigator.pop();
  }
  render(){
    return (
      <View style={styles.secondView}>
        <TouchableHighlight
         style={{padding:10}}
         onPress={this.toFirst}
         underlayColor="red">
           <Text style={styles.contentText}>{this.props.data}</Text>
        </TouchableHighlight>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  backImage:{
    width:15,
    height:30,
  },
 navBarTitleText: {
   color: 'black',
   fontWeight: '500',
   marginTop:20,
 },
 navBarLeftButton: {
   paddingLeft: 10,
   paddingTop:15,
 },
 navBarRightButton: {
   paddingRight: 10,
   paddingTop:20,
 },
 navBarButtonText: {
   color: '#5890FF',
 },
  container: {
    flex: 1,
  },
  firstView:{
    flex: 1,
    backgroundColor:'red',
    justifyContent: 'center',
  },
  secondView:{
    flex:1,
    justifyContent: 'center',
    backgroundColor:'blue',
  },
  contentText:{
    fontSize:22,
    color:'white',
    textAlign:'center',
  },
});

AppRegistry.registerComponent('NavigatorDemo', () => NavigatorDemo);