React-Native组件之 Navigator和NavigatorIOS

来源:互联网 发布:iphone蓝牙传输软件 编辑:程序博客网 时间:2024/06/05 18:53

对于app而言,一款应用往往涉及到很多的页面,而页面之间的跳转Android和iOS实现也各不相同。在iOS上,系统为我们提供了UINavigationController控件用来专门控制页面的跳转,iOS的实现思路很清晰,为按钮添加action事件,点击之后跳转到指定的页面即可。例如:

//定义一个Button,点击后跳转到另一个页面    UIButton * button=[UIButton buttonWithType:UIButtonTypeSystem];    button.frame=CGRectMake(130, 220, 100, 30);    [button addTarget:self action:@selector(toNext)      forControlEvents:UIControlEventTouchUpInside];    [button setTitle:@"跳转登录" forState:UIControlStateNormal];[self.view addSubview:button];//省略…-(void)toNext{    UIBarButtonItem * back=[[UIBarButtonItem alloc]init];    back.title = @"返回";    self.navigationItem.backBarButtonItem = back;    SecondViewController * second = [[SecondViewController alloc]init];    [self.navigationController pushViewController:second animated:YES];}

对于Android来说,Android的跳转通过Intent来进行跳转,而返回等操作,Android一般为我们实现了物理返回和软件返回两种。物理返回我们一般通过捕捉onKeyDown用户事件,而软件返回主要通过在界面上添加返回按钮实现页面的返回操作。

Navigator 与 NavigatorIOS

在移动开发过程中,几乎所有的APP中或多或少都会涉及到多个界面间的切换,在React Native中有两个组件负责实现这样的效果 —— Navigator 和 NavigatorIOS。Navigator可以在iOS和Android同时使用,而NavigatorIOS则是包装了UIKit库的导航功能,使用户可以使用左划功能来返回到上一界面。

Navigator常见的属性如下:

属性 类型 说明 initialRoute object 导航的初始route(第一个显示的); initialRouteStack object 导航的route集合,如果initialRoute没有设置,这个属性是必填的。如果这个属性没有,它将会默认传递一个仅仅包含initialRoute的集合; renderScene function 必填的方法,它根据给定的ruote渲染夜间,将被使用route和navigator对象参数调用; navigationBar view 导航的可选组件导航标题栏,需要设置左按钮,右按钮和标题属性。这个组件将会获取两个属性:navigator和navState代表导航组件和它的状态。这个组件当ruote改变的时候会重新渲染; configureScene function 可选的方法,你可以通过它配置页面切换的动画和手势。将会使用route和routeStack参数调用,route代表导航当前显示的页面,routeStack是导航当前展示的route集合;

1,首先,创建2个组件(home、Temp)并初始化组件

代码如下:
home组件

import React, { Component } from 'react';  import {      AppRegistry,      StyleSheet,      Text,      View  } from 'react-native';  var Home = React.createClass( {      render() {          return (              <View style={styles.container}>                  <Text>点击跳转</Text>              </View>          );      }  });  var styles = StyleSheet.create({      container: {          backgroundColor:'yellow',          flex:1,          justifyContent:'center',          alignItems:'center'      },  });  module.exports = Home;

temp组件

 import React, { Component } from 'react';  import {      AppRegistry,      StyleSheet,      Text,      View  } from 'react-native';  var Temp = React.createClass( {      render() {          return (              <View style={styles.container}>                  <Text>点击返回</Text>              </View>          );      }  });  var styles = StyleSheet.create({      container: {          backgroundColor:'yellow',          flex:1,          justifyContent:'center',          alignItems:'center'      },  });  module.exports = Temp;

实例化 Navigator的属性:initialRoute 和 renderSence,它们的作用分别是告诉导航器需要渲染的场景、根据路由描述渲染出来。

      <Navigator          style={{flex: 1}}        // 布局          initialRoute={{              name:'Home',    // 名称              component:Home  // 要跳转的板块          }}          renderScene={(route, navigator) => {    // 将板块生成具体的组件                  let Component = route.component;    // 获取路由内的板块                  return <Component {...route.params} navigator={navigator} />    // 根据板块生成具体组件          }}      />

项目实例

比如我们要实现两个页面的切换效果,当点击返回的时候可以返回之前的页面,如图所示:
这里写图片描述
这里写图片描述
要实现上面的效果,需要三个文件:第一个页面,第二个页面和一个控制跳转的JS。
导航控制页面,

/** * Sample React Native App * https://github.com/facebook/react-native * @flow */import React, { Component } from 'react';import Splash from './src/widght/ProductList';import {  AppRegistry,  StyleSheet,  Platform,  TouchableOpacity,  Text,  StatusBar,  Navigator,  ListView,  Image,  View} from 'react-native';const defaultRoute = {    component: Splash};export default class Demo extends Component {  renderScene(route, navigator) {        let Component = route.component;        return (            <Component {...route.params} navigator={navigator}/>        );    }    renderNavBar() {        var routeMapper = {            LeftButton(route, navigator, index, navState) {//左边按钮                if (index > 0) {                    return (                        <TouchableOpacity                            onPress={() => navigator.pop()}//退栈                            style={styles.button}>                            <Image                                style={styles.thumbnail}                                source={require('./image/back_gray_icon.png')}                            />                        </TouchableOpacity>                    );                }            },            RightButton(route, navigator, index, navState) {//右边按钮            },            Title(route, navigator, index, navState) {//主标题                return (                    <View style={styles.title}>                        <Text style={styles.buttonText}>{!route.title ? '商品列表' : '商品详情'}</Text>                    </View>                );            }        };        return (            <Navigator.NavigationBar                style={styles.navigationBarStyle}                routeMapper={routeMapper}            />        );    }    render() {        return (            <Navigator                initialRoute={defaultRoute}                renderScene={this.renderScene}                sceneStyle={{paddingTop: (Platform.OS === 'android' ? 66 : 74)}}                navigationBar={this.renderNavBar()}/>        );    }}const styles = StyleSheet.create({    container: {        flex: 1,        justifyContent: 'center',        alignItems: 'center',        backgroundColor: '#F5FCFF',    },    navigationBarStyle:{      alignItems: 'center',      backgroundColor: '#FFFFFF',      shadowOffset: {          width: 1,          height: 0.5,      },      shadowColor: '#999999',      shadowOpacity: 0.2,    },    title: {        flex: 1,        alignItems: 'center',        justifyContent: 'center',        backgroundColor:'#FFFFFF'    },    button: {        flex: 1,        width: 50,        alignItems: 'center',        justifyContent: 'center'    },    buttonText: {        fontSize: 18,        justifyContent: 'center',        alignItems: 'center',        color: '#999999',        fontWeight: '800'    },    thumbnail: {         width: 40,         height: 40     }});AppRegistry.registerComponent('Demo', () => Demo);

商品列表ProductList.js

/** * https://github.com/facebook/react-native * @flow */import React, { Component } from 'react';import { View, Text,Image, StyleSheet,TouchableOpacity} from 'react-native';import ProductDetail from './ProductDetail';class ProductList extends Component {  openPage() {        this.props.navigator.push({            title: 'ProductDetail',            component: ProductDetail        })    }    render() {        return (            <View style={styles.container}>                <TouchableOpacity onPress={this.openPage.bind(this)}>                    <Text style={styles.textStyle}>点我跳转第二个页面</Text>                </TouchableOpacity>            </View>        );    }}const styles = StyleSheet.create({    container: {          flex: 1,          justifyContent: 'center',          alignItems: 'center',          backgroundColor: '#FFFFFF'    },    textStyle: {        fontSize: 20,        color:'#55ACEE',        marginBottom: 8,        textAlign: 'left'    }});export default ProductList;

商品详情页面,ProductDetail.js

/** * https://github.com/facebook/react-native * @flow 闪屏页 */import React, { Component } from 'react';import { View, Text,Image, StyleSheet,TextInput,TouchableOpacity} from 'react-native';class ProductDetail extends Component {    render() {        return (            <View style={styles.container}>                <Text style={styles.detail}>商品详情页</Text>            </View>        );    }}const styles = StyleSheet.create({  container: {    flex: 1,    justifyContent: 'center',    alignItems: 'center',    backgroundColor: '#FFFFFF',  },  detail: {    fontSize: 24,    textAlign: 'center',  }});export default ProductDetail;

Navigator内置了很多动画跳转。如:

  • Navigator.SceneConfigs.PushFromRight 从右边进入
 (route, routeStack) => Navigator.SceneConfigs.FloatFromRight
  • Navigator.SceneConfigs.FloatFromLeft 从左边进入
  (route, routeStack) => Navigator.SceneConfigs.FloatFromLeft
  • Navigator.SceneConfigs.FloatFromBottom 从底部进入
  • Navigator.SceneConfigs.FloatFromBottomAndroid
  (route, routeStack) => Navigator.SceneConfigs.FloatFromBottom
  • Navigator.SceneConfigs.FadeAndroid Android飞入效果
(route, routeStack) => Navigator.SceneConfigs.FadeAndroid
  • Navigator.SceneConfigs.HorizontalSwipeJump 水平跳入
 (route, routeStack) => Navigator.SceneConfigs.HorizontalSwipeJump

除此之外,还有很多动画效果,这里不再依依说明。

对于NavigatorIOS而言,主要有以下属性:

属性 说明 barTintColor 导航条的背景颜色 itemWrapperStyle 导航器中的组件的默认属性。一个常见的用途是设置所有页面的背景颜色 navigationBarHidden 布尔值,决定导航栏是否隐藏 shadowHidden 布尔值,决定是否要隐藏1像素的阴影 tintColor 导航栏上按钮的颜色 titleTextColor 导航器标题的文字颜色 translucent 布尔值,决定导航条是否半透明(注:当不半透明时页面会向下移动导航栏等高的距离,以防止内容被遮盖) interactivePopGestureEnabled 决定是否启用滑动返回手势。不指定此属性时,手势会根据 navigationBar 的显隐情况决定是否启用(显示时启用手势,隐藏时禁用手势),指定此属性后,手势与 navigationBar 的显隐情况无关

除了上面的属性之外,还有一些常用的方法:
push(route) 导航器跳转到一个新的路由
pop()返回到上一页
replace(route)替换当前页的路由,并立即加载新路由的视图
replacePreviousAndPop(route)替换上一页的路由/视图并且立即切换回上一页
resetTO(route)替换最顶级的路由并且回到它
replaceAtIndex替换指定路由
popToRoute(route)一直回到某个指定的路由

和 Navigator 一样 NavigatorIOS 需要有个根视图来完成初始化,所以我们需要先创建一个组件来描述这个界面,并将这个组件通过路由的形式告诉 NavigatorIOS。
1,创建一个 Home 组件,用来作为 NavigatorIOS 的根视图

 var Home = React.createClass( {      render() {          return (              <View style={styles.container}>                     <Text>点击跳转页面</Text>              </View>          );      }  });   var styles = StyleSheet.create({      container: {          // 背景颜色          backgroundColor:'yellow',          flex:1,          // 对齐方式          justifyContent:'center',          alignItems:'center'      },  });

然后我们实例化一个 NavigatorIOS 并设置路由。

  var navigatorDemo = React.createClass( {        render() {          return (              <NavigatorIOS                  initialRoute={{                      component: Home,    // 要跳转的页面                      title:'首页'    // 跳转页面导航栏标题                  }}                  style={{flex:1}}  // 此项不设置,创建的导航控制器只能看见导航条而看不到界面              />          );        }  });

然后通过TouchableOpacity点击跳转。
这里写图片描述

左边返回按钮的样式:

initialRoute={{         component: Home,    // 要跳转的页面         title:'首页',   // 跳转页面导航栏标题         leftButtonTitle:'左边',   // 实例化左边按钮         onLeftButtonPress:() => {alert('左边')},  // 左边按钮点击事件         rightButtonTitle:'右边',  // 实例化右边按钮         onRightButtonPress:() => {alert('右边')}  // 右边按钮点击事件          }}

为了实现类似Android导航栏的功能,React Native提供了NavigationBar(类似于Android的Toolbar)。关于NavigationBar这里不再详述。

第三方库

React Native Simple Router是一款第三方导航组件,你可以通过它进行合理的视图组织。
react-navigation,一款可以替换React Native Simple Router的导航器组件,使用比较简单。

附:示例代码
React Native常用第三方库

1 4