React-Native中导航组件react-navigation的使用

Posted YanceChen2013

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了React-Native中导航组件react-navigation的使用相关的知识,希望对你有一定的参考价值。

写在开头的话

最近使用React-Native开发新应用,一开始使用的导航器是navigator,后来发现navigator有很多不足之处,而且官方也建议使用react-navigation来进行开发,所以现在转为使用react-navigation开发新应用了。

总览

React Native 中,官方已经推荐使用 react-navigation 来实现各个界面的跳转和不同板块的切换。react-navigation据称有原生般的性能体验效果。可能会成为未来React Native导航组件的主流军。该库主要有三个部分组成:
1、 StackNavigator: 类似于普通的Navigator,屏幕上方导航栏,用于实现各个页面之间的跳转
2、 TabNavigator: 相当于ios里面的TabBarController,屏幕下方的标签栏,主要用于同一个页面上不同界面之间的切换
3、 DrawerNavigator: 抽屉效果,侧边滑出

StackNavigator 导航栏

StackNavigator 组件采用堆栈式的页面导航来实现各个界面跳转。
首先如果想要使用StackNavigator,一定要先注册导航。

const Navigator = StackNavigator(
    
        Tab:  screen: Tab ,
        Web:  screen: WebScene ,
        GroupPurchase:  screen: GroupPurchaseScene ,
    ,
    
        navigationOptions: 
            // headerStyle:  backgroundColor: color.theme 
            headerBackTitle: null,
            headerTintColor: '#333333',
            showIcon: true,
        ,
    
);

这里配置了给导航器配置了三个界面,如果需要更多界面,可以在之后进行添加。主要有一个用于主界面之间能够切换的Tab界面和其他两个能够展示数据的界面。

StackNavigatorConfig 导航器的配置

  • initialRouteName - 导航器组件中初始显示页面的路由名称,如果不设置,则默认第一个路由页面为初始显示页面
  • initialRouteParams - 给初始路由的参数,在初始显示的页面中可以通过 this.props.navigation.state.params 来获取
  • navigationOptions - 路由页面的配置选项,它会被 RouteConfigs 参数中的navigationOptions 的对应属性覆盖。
  • paths - 路由中设置的路径的覆盖映射配置
  • mode - 页面跳转方式,有 card 和 modal 两种,默认为 card :

    card - 原生系统默认的的跳转,左右互换
    modal - 只针对iOS平台,模态跳转,上下切换

  • headerMode - 页面跳转时,头部的动画模式,有 float 、 screen 、 none 三种:

    float - 渐变,类似iOS的原生效果,无透明
    screen - 标题与屏幕一起淡入淡出,如微信一样
    none - 没有动画

  • cardStyle - 为各个页面设置统一的样式,比如背景色,字体大小等
  • transitionConfig - 配置页面跳转的动画,覆盖默认的动画效果
  • onTransitionStart - 页面跳转动画即将开始时调用
  • onTransitionEnd - 页面跳转动画一旦完成会马上调用
    代码示例:
const StackNavigatorConfig = 
    initialRouteName: 'Home',
    initialRouteParams: initPara: '初始页面参数',
    navigationOptions: 
        title: '标题',
        headerTitleStyle: fontSize: 18, color: '#666666',
        headerStyle: height: 48, backgroundColor: '#
',
    ,
    paths: 'page/main',
    mode: 'card',
    headerMode: 'screen',
    cardStyle: backgroundColor: "#ffffff",
    transitionConfig: (() => (
        screenInterpolator: CardStackStyleInterpolator.forHorizontal,
    )),
    onTransitionStart: (() => 
        console.log('页面跳转动画开始');
    ),
    onTransitionEnd: (() => 
        console.log('页面跳转动画结束');
    ),
;
  • title - 可以作为头部标题 headerTitle ,或者Tab标题 tabBarLabel
  • header - 自定义的头部组件,使用该属性后系统的头部组件会消失,如果想在页面中自定义,可以设置为null,这样就不会出现页面中留有一个高度为64navigationBar的高度
  • headerTitle - 头部的标题,即页面的标题
  • headerBackTitle - 返回标题,默认为 title
  • headerTruncatedBackTitle - 返回标题不能显示时(比如返回标题太长了)显示此标题,默认为 “Back”
  • headerRight - 头部右边组件
  • headerLeft - 头部左边组件
  • headerStyle - 头部组件的样式
  • headerTitleStyle - 头部标题的样式
  • headerBackTitleStyle - 头部返回标题的样式
  • headerTintColor - 头部颜色
  • headerPressColorandroid - Android 5.0 以上MD风格的波纹颜色
  • gesturesEnabled - 否能侧滑返回, iOS 默认 true , Android 默认 false
    使用示例
// 注册导航
const Navs = StackNavigator(
    Home:  screen: Tabs ,
    HomeTwo: 
        screen: HomeTwo,  // 必须, 其他都是非必须
        path:'app/homeTwo', 使用url导航时用到, 如 web app 和 Deep Linking
        navigationOptions:   // 此处设置了, 会覆盖组件内的`static navigationOptions`设置. 具体参数详见下文
    ,
    HomeThree:  screen: HomeThree ,
    HomeFour:  screen: HomeFour 
, 
    initialRouteName: 'Home', // 默认显示界面
    navigationOptions:   // 屏幕导航的默认选项, 也可以在组件内用 static navigationOptions 设置(会覆盖此处的设置)
        header:   // 导航栏相关设置项
            backTitle: '返回',  // 左上角返回键文字
            style: 
                backgroundColor: '#fff'
            ,
            titleStyle: 
                color: 'green'
            
        ,
        cardStack: 
            gesturesEnabled: true
        
    , 
    mode: 'card',  // 页面切换模式, 左右是card(相当于iOS中的push效果), 上下是modal(相当于iOS中的modal效果)
    headerMode: 'screen', // 导航栏的显示模式, screen: 有渐变透明效果, float: 无透明效果, none: 隐藏导航栏
    onTransitionStart: ()=> console.log('导航栏切换开始'); ,  // 回调
    onTransitionEnd: ()=> console.log('导航栏切换结束');   // 回调
);

当然页面配置选项 navigationOptions 还可以在对应页面中去静态配置。


    // 配置页面导航选项
    static navigationOptions = (navigation) => (
        title: 'HOME',
        titleStyle: color: '#ff00ff',
        headerStyle:backgroundColor:'#000000'
    );

    render() 
        return (
            <View></View>
        )
    ;

在页面里面采用静态的方式配置 navigationOptions 中的属性,会覆盖 StackNavigator 构造函数中两个参数 RouteConfigs 和 StackNavigatorConfig 配置的 navigationOptions 里面的对应属性。 navigationOptions 中属性的优先级是:
页面中静态配置 > RouteConfigs > StackNavigatorConfig
我们可以在组件中直接使用该配置了,当然我们也可以像文章开头提过的那样使用:

const Navigator = StackNavigator(RouteConfigs, StackNavigatorConfig);

export default class Main extends Component 
    render() 
        return (
            <Navigator/>
        )
    ;

好了,我们到此已经配置好导航器和对应的路由页面了,但是我们还需要navigation才能实现页面的跳转。

在导航器中的每一个页面,都有 navigation 属性,该属性有以下几个属性/方法,可以在组件下console.log一下this.props就能看到。

  • navigate - 跳转到其他页面
  • state - 当前页面导航器的状态
  • setParams - 更改路由的参数
  • goBack - 返回
  • dispatch - 发送一个action

this.props.navigation.navigate(‘Two’, name: ‘two’ ): push下一个页面

◦   routeName: 注册过的目标路由名称
◦   params: 传递的参数,传递到下一级界面
◦   action: 如果该界面是一个navigator的话,将运行这个sub-action

state

state 里面包含有传递过来的参数 params、key 、路由名称 routeName

◦   routeName: 路由名
◦   key: 路由身份标识
◦   params: 参数

setParams

this.props.navigation.setParams: 该方法允许界面更改router中的参数,可以用来动态的更改导航栏的内容。比如可以用来更新头部的按钮或者标题。

goBack

返回上一页,可以不传参数,也可以传参数,还可以传 null 。

this.props.navigation.goBack();       // 回退到上一个页面
this.props.navigation.goBack(null);   // 回退到任意一个页面
this.props.navigation.goBack('Home'); // 回退到Home页面

dispatch

this.props.navigation.dispatch: 可以dispatch一些action,主要支持的action有:

  • Navigate:
import  NavigationActions  from 'react-navigation'

  const navigationAction = NavigationActions.navigate(
    routeName: 'Profile',
    params: ,

    // navigate can have a nested navigate action that will be run inside the child router
    action: NavigationActions.navigate( routeName: 'SubProfileRoute')
  )
  this.props.navigation.dispatch(navigationAction)
  • Reset: Reset方法会清除原来的路由记录,添加上新设置的路由信息, 可以指定多个action,index是指定默认显示的那个路由页面, 注意不要越界了
import  NavigationActions  from 'react-navigation'

  const resetAction = NavigationActions.reset(
    index: 0,
    actions: [
      NavigationActions.navigate( routeName: 'Profile'),
      NavigationActions.navigate( routeName: 'Two')
    ]
  )
  this.props.navigation.dispatch(resetAction)
  • SetParams: 为指定的router更新参数,该参数必须是已经存在于router的param中
  import  NavigationActions  from 'react-navigation'

  const setParamsAction = NavigationActions.setParams(
    params: , // these are the new params that will be merged into the existing route params
    // The key of the route that should get the new params
    key: 'screen-123',
  )
  this.props.navigation.dispatch(setParamsAction)

页面跳转,传值,回调传参

跳转,传值

  const navigate = this.props.navigation;
  <TouchableHighlight onPress=()=>
       navigate('PlanDetail',name:'leslie',id:100);
  >

  // 返回上一页
  this.props.navigation.goBack();

在下一界面接收参数
通过 this.props.navigation.state.params 接收参数

export default class Home1 extends Component 
      static navigationOptions = 
          // title 可以这样设置成一个函数, state 会自动传过来
          title: (state) => `$state.params.name`,
      ;

      componentDidMount() 
          const params = this.props.navigation.state;
          const id = params.id;
      
    

回调传参

当前界面进行跳转

navigate('Detail',
   // 跳转的时候携带一个参数去下个页面
   callback: (data)=>
         console.log(data); // 打印值为:'回调参数'
     
  );

下一界面在返回之前传参

const navigate,goBack,state = this.props.navigation;
// 在第二个页面,在goBack之前,将上个页面的方法取到,并回传参数,这样回传的参数会重走render方法
state.params.callback('回调参数');
goBack();

TabNavigator 即是Tab选项卡

TabNavigator(RouteConfigs, TabNavigatorConfig)

api和 StackNavigator 类似,参数 RouteConfigs 是路由配置,参数 TabNavigatorConfig是Tab选项卡配置。

RouteConfigs 路由配置

路由配置和 StackNavigator 中是一样的,配置路由以及对应的 screen 页面,navigationOptions 为对应路由页面的配置选项:

  • title - Tab标题,可用作headerTitle 和 tabBarLabel 回退标题
  • tabBarVisible - Tab的是否可见,没有设置的话默认为 true
  • tabBarIcon - Tab的icon组件,可以根据 focused: boolean, tintColor: string 方法来返回一个icon组件
  • tabBarLabel - Tab中显示的标题字符串或者组件,也可以根据 focused: boolean, tintColor: string 方法返回一个组件
    代码示例:
Mine: 
            screen: MineScene,
            navigationOptions: ( navigation ) => (
                tabBarLabel: '我的',
                tabBarIcon: ( focused, tintColor ) => (
                    <TabBarItem
                        tintColor=tintColor
                        focused=focused
                        normalImage=require('./img/tabbar/pfb_tabbar_mine@2x.png')
                        selectedImage=require('./img/tabbar/pfb_tabbar_mine_selected@2x.png')
                    />
                )
            ),
        ,

TabBarItem自定义组件

class TabBarItem extends PureComponent 
    render() 
        let selectedImage = this.props.selectedImage ? this.props.selectedImage : this.props.normalImage
        return (
            <Image
                source=this.props.focused
                    ? selectedImage
                    : this.props.normalImage
                style= tintColor: this.props.tintColor, width: 25, height: 25 
            />
        );
    

TabNavigatorConfig Tab选项卡配置

  • tabBarComponent - Tab选项卡组件,有 TabBarBottom 和 TabBarTop 两个值,在iOS中默认为 TabBarBottom ,在Android中默认为 TabBarTop 。

    TabBarTop - 在页面的顶部
    TabBarBottom - 在页面的底部

  • tabBarPosition - Tab选项卡的位置,有top或bottom两个值
    top:上面
    bottom:下面
  • swipeEnabled - 是否可以滑动切换Tab选项卡
  • animationEnabled - 点击Tab选项卡切换界面是否需要动画
  • lazy - 是否懒加载页面
  • initialRouteName - 初始显示的Tab对应的页面路由名称
  • order - 用路由名称数组来表示Tab选项卡的顺序,默认为路由配置顺序
  • paths - 路径配置
  • backBehavior - androd点击返回键时的处理,有 initialRoute 和 none 两个值

    initailRoute - 返回初始界面
    none - 退出

  • tabBarOptions - Tab配置属性,用在TabBarTop和TabBarBottom时有些属性不一致:

    用于 TabBarTop 时:

    • activeTintColor - 选中的文字颜色
    • inactiveTintColor - 未选中的文字颜色
    • showIcon - 是否显示图标,默认显示
    • showLabel - 是否显示标签,默认显示
    • upperCaseLabel - 是否使用大写字母,默认使用
    • pressColor - android 5.0以上的MD风格波纹颜色
    • pressOpacity - android 5.0以下或者iOS按下的透明度
    • scrollEnabled - 是否可以滚动
    • tabStyle - 单个Tab的样式
    • indicatorStyle - 指示器的样式
    • labelStyle - 标签的样式
    • iconStyle - icon的样式
    • style - 整个TabBar的样式

    用于 TabBarBottom 时:

    • activeTintColor - 选中Tab的文字颜色
    • inactiveTintColor - 未选中Tab的的文字颜色
    • activeBackgroundColor - 选中Tab的背景颜色
    • inactiveBackgroundColor - 未选中Tab的背景颜色
    • showLabel - 是否显示标题,默认显示
    • style - 整个TabBar的样式
    • labelStyle - 标签的样式
    • tabStyle - 单个Tab的样式

使用底部选项卡:

import React, Component from 'react';
import StackNavigator, TabBarBottom, TabNavigator from "react-navigation";
import HomeScreen from "./index18/HomeScreen";
import NearByScreen from "./index18/NearByScreen";
import MineScreen from "./index18/MineScreen";
import TabBarItem from "./index18/TabBarItem";
export default class MainComponent extends Component 
    render() 
        return (
            <Navigator/>
        );
    


const TabRouteConfigs = 
    Home: 
        screen: HomeScreen,
        navigationOptions: (navigation) => (
            tabBarLabel: '首页',
            tabBarIcon: (focused, tintColor) => (
                <TabBarItem
                    tintColor=tintColor
                    focused=focused
                    normalImage=require('./img/tabbar/pfb_tabbar_homepage_2x.png')
                    selectedImage=require('./img/tabbar/pfb_tabbar_homepage_selected_2x.png')
                />
            ),
        ),
    ,
    NearBy: 
        screen: NearByScreen,
        navigationOptions: 
            tabBarLabel: '附近',
            tabBarIcon: (focused, tintColor) => (
                <TabBarItem
                    tintColor=tintColor
                    focused=focused
                    normalImage=require('./img/tabbar/pfb_tabbar_merchant_2x.png')
                    selectedImage=require('./img/tabbar/pfb_tabbar_merchant_selected_2x.png')
                />
            ),
        ,
    
    ,
    Mine: 
        screen: MineScreen,
        navigationOptions: 
            tabBarLabel: '我的',
            tabBarIcon: (focused, tintColor) => (
                <TabBarItem
                    tintColor=tintColor
                    focused=focused
                    normalImage=require('./img/tabbar/pfb_tabbar_mine_2x.png')
                    selectedImage=require('./img/tabbar/pfb_tabbar_mine_selected_2x.png')
                />
            ),
        ,
    
;
const TabNavigatorConfigs = 
    initialRouteName: 'Home',
    tabBarComponent: TabBarBottom,
    tabBarPosition: 'bottom',
    lazy: true,
;
const Tab = TabNavigator(TabRouteConfigs, TabNavigatorConfigs);
const StackRouteConfigs = 
    Tab: 
        screen: Tab,
    
;
const StackNavigatorConfigs = 
    initialRouteName: 'Tab',
    navigationOptions: 
        title: '标题',
        headerStyle: backgroundColor: '#5da8ff',
        headerTitleStyle: color: '#333333',
    
;
const Navigator = StackNavigator(StackRouteConfigs, StackNavigatorConfigs);

使用顶部选项卡:

import React, Component from "react";
import StackNavigator, TabBarTop, TabNavigator from "react-navigation";
import HomeScreen from "./index18/HomeScreen";
import NearByScreen from "./index18/NearByScreen";
import MineScreen from "./index18/MineScreen";
export default class MainComponent extends Component 
    render() 
        return (
            <Navigator/>
        );
    


const TabRouteConfigs = 
    Home: 
        screen: HomeScreen,
        navigationOptions: (navigation) => (
            tabBarLabel: '首页',
        ),
    ,
    NearBy: 
        screen: NearByScreen,
        navigationOptions: 
            tabBarLabel: '附近',
        ,
    
    ,
    Mine: 
        screen: MineScreen,
        navigationOptions: 
            tabBarLabel: '我的',
        ,
    
;
const TabNavigatorConfigs = 
    initialRouteName: 'Home',
    tabBarComponent: TabBarTop,
    tabBarPosition: 'top',
    lazy: true,
    tabBarOptions: 
;
const Tab = TabNavigator(TabRouteConfigs, TabNavigatorConfigs);
const StackRouteConfigs = 
    Tab: 
        screen: Tab,
    
;
const StackNavigatorConfigs = 
    initialRouteName: 'Tab',
    navigationOptions: 
        title: '标题',
        headerStyle: backgroundColor: '#5da8ff',
        headerTitleStyle: color: '#333333',
    
;
const Navigator = StackNavigator(StackRouteConfigs, StackNavigatorConfigs);

DrawerNavigator 抽屉导航

有一些APP都会采用侧滑抽屉来做主页面的导航,利用 DrawerNavigator 在RN中可以很方便来实现抽屉导航。

DrawerNavigator(RouteConfigs, DrawerNavigatorConfig)

和TabNavigator的构造函数一样,参数配置也类似

RouteConfigs

抽屉导航的路由配置 RouteConfigs ,和 TabNavigator 的路由配置完全一样, screen 配置对应路由页面, navigationOptions 为对应页面的抽屉配置选项:

  • title - 抽屉标题,和 headerTitle 、 drawerLabel 一样
  • drawerLabel - 标签字符串,或者自定义组件, 可以根据 focused: boolean, tintColor: string 函数来返回一个自定义组件作为标签
  • drawerIcon - 抽屉icon,可以根据 focused: boolean, tintColor: string 函数来返回一个自定义组件作为icon

DrawerNavigatorConfig 属性配置

  • drawerWidth - 抽屉宽度,可以使用Dimensions获取屏幕的宽度,动态计算
  • drawerPosition - 抽屉位置,可以是 left 或者 right
  • contentComponent - 抽屉内容组件,可以自定义侧滑抽屉中的所有内容,默认为 DrawerItems
  • contentOptions - 用来配置抽屉内容的属性。当用来配置 DrawerItems 是配置属性选项:
    • items - 抽屉栏目的路由名称数组,可以被修改
    • activeItemKey - 当前选中页面的key id
    • activeTintColor - 选中条目状态的文字颜色
    • activeBackgroundColor - 选中条目的背景色
    • inactiveTintColor - 未选中条目状态的文字颜色
    • inactiveBackgroundColor - 未选中条目的背景色
    • onItemPress(route) - 条目按下时会调用此方法
    • style - 抽屉内容的样式
    • labelStyle - 抽屉的条目标题/标签样式
  • initialRouteName - 初始化展示的页面路由名称
  • order - 抽屉导航栏目顺序,用路由名称数组表示
  • paths - 路径
  • backBehavior - androd点击返回键时的处理,有initialRoute和none两个值,initailRoute:返回初始界面, none :退出
    抽屉导航示例:
import React, Component from 'react';
import DrawerNavigator, StackNavigator, TabBarBottom, TabNavigator from "react-navigation";
import HomeScreen from "./index18/HomeScreen";
import NearByScreen from "./index18/NearByScreen";
import MineScreen from "./index18/MineScreen";
import TabBarItem from "./index18/TabBarItem";
export default class MainComponent extends Component 
    render() 
        return (
            <Navigator/>
        );
    

const DrawerRouteConfigs = 
    Home: 
        screen: HomeScreen,
        navigationOptions: (navigation) => (
            drawerLabel : '首页',
            drawerIcon : (focused, tintColor) => (
                <TabBarItem
                    tintColor=tintColor
                    focused=focused
                    normalImage=require('./img/tabbar/pfb_tabbar_homepage_2x.png')
                    selectedImage=require('./img/tabbar/pfb_tabbar_homepage_selected_2x.png')
                />
            ),
        ),
    ,
    NearBy: 
        screen: NearByScreen,
        navigationOptions: 
            drawerLabel : '附近',
            drawerIcon : (focused, tintColor) => (
                <TabBarItem
                    tintColor=tintColor
                    focused=focused
                    normalImage=require('./img/tabbar/pfb_tabbar_merchant_2x.png')
                    selectedImage=require('./img/tabbar/pfb_tabbar_merchant_selected_2x.png')
                />
            ),
        ,
    ,
    Mine: 
        screen: MineScreen,
        navigationOptions: 
            drawerLabel : '我的',
            drawerIcon : (focused, tintColor) => (
                <TabBarItem
                    tintColor=tintColor
                    focused=focused
                    normalImage=require('./img/tabbar/pfb_tabbar_mine_2x.png')
                    selectedImage=require('./img/tabbar/pfb_tabbar_mine_selected_2x.png')
                />
            ),
        ,
    
;
const DrawerNavigatorConfigs = 
    initialRouteName: 'Home',
    tabBarComponent: TabBarBottom,
    tabBarPosition: 'bottom',
    lazy: true,
    tabBarOptions: 
;
const Drawer = DrawerNavigator(DrawerRouteConfigs, DrawerNavigatorConfigs);
const StackRouteConfigs = 
    Drawer: 
        screen: Drawer,
    
;
const StackNavigatorConfigs = 
    initialRouteName: 'Drawer',
    navigationOptions: 
        title: '标题',
        headerStyle: backgroundColor: '#5da8ff',
        headerTitleStyle: color: '#333333',
    
;
const Navigator = StackNavigator(StackRouteConfigs, StackNavigatorConfigs);

扩展功能

  • 默认DrawerView不可滚动。要实现可滚动视图,必须使用contentComponent自定义容器
  
  drawerWidth:200,  
  抽屉位置:“对”  
  contentComponent:props => <ScrollView> <DrawerItems ... props></DrawerItems> </ ScrollView>  
  • 可以覆盖导航使用的默认组件,使用DrawerItems自定义导航组件
import DrawerItems from 'react-navigation';  

const CustomDrawerContentComponent = (props) => (  
  <View style = style.container>  
    <DrawerItems ... props />  
  </View>    
); 
  • 嵌套抽屉导航
    如果您嵌套DrawerNavigation,抽屉将显示在父导航下方。

自定义react-navigation

  • 适配顶部导航栏标题

测试中发现,在iphone上标题栏的标题为居中状态,而在Android上则是居左对齐。所以需要我们修改源码,进行适配。
【node_modules – react-navigation – src – views – Header.js】的326行代码处,修改为如下:

title:   
   bottom: 0,  
   left: TITLE_OFFSET,  
   right: TITLE_OFFSET,  
   top: 0,  
   position: 'absolute',  
   alignItems: 'center',  
  

上面方法通过修改源码的方式其实略有弊端,毕竟扩展性不好。还有另外一种方式就是,在navigationOptions中设置headerTitleStyle的alignSelf为 ’ center ‘即可解决。
* 去除返回键文字显示

【node_modules – react-navigation – src – views – HeaderBackButton.js】的91行代码处,修改为如下即可。

 
   Platform.OS === 'ios' &&  
     title &&  
     <Text  
       onLayout=this._onTextLayout  
       style=[styles.title,  color: tintColor ]  
       numberOfLines=1  
     >  
       backButtonTitle  
     </Text>
   

将上述代码删除即可。

  • 动态设置头部按钮事件

当我们在头部设置左右按钮时,肯定避免不了要设置按钮的单击事件,但是此时会有一个问题,navigationOptions是被修饰为static类型的,所以我们在按钮的onPress的方法中不能直接通过this来调用Component中的方法。如何解决呢?在官方文档中,作者给出利用设置params的思想来动态设置头部标题。那么我们可以利用这种方式,将单击回调函数以参数的方式传递到params,然后在navigationOption中利用navigation来取出设置到onPress即可:

  componentDidMount ()   
      /**  
       * 将单击回调函数作为参数传递  
       */  
      this.props.navigation.setParams(  
              switch: () => this.switchView()  
      );  
    
  /**  
 * 切换视图  
 */  
switchView()   
    alert('切换')  
  
static navigationOptions = (navigation,screenProps) => (  
    headerTitle: '企业服务',  
    headerTitleStyle: CommonStyles.headerTitleStyle,  
    headerRight: (  
        <NavigatorItem icon= Images.ic_navigator  onPress= ()=> navigation.state.params.switch() />  
    ),  
    headerStyle: CommonStyles.headerStyle  
); 
  • 结合BackHandler处理返回和点击返回键两次退出App效果
    点击返回键两次退出App效果的需求屡见不鲜。相信很多人在react-navigation下实现该功能都遇到了很多问题,例如,其他界面不能返回。也就是手机本身返回事件在react-navigation之前拦截了。如何结合react-natigation实现呢?和大家分享两种实现方式:

    (1)在注册StackNavigator的界面中,注册BackHandler

componentWillMount()  
    BackHandler.addEventListener('hardwareBackPress', this._onBackAndroid );  
  


componentUnWillMount()  
    BackHandler.addEventListener('hardwareBackPress', this._onBackAndroid);  
  

_onBackAndroid=()=>  
    let now = new Date().getTime();  
    if(now - lastBackPressed < 2500)   
        return false;  
      
    lastBackPressed = now;  
    ToastAndroid.show('再点击一次退出应用',ToastAndroid.SHORT);  
    return true;  
 

(2)监听react-navigation的Router

/** 
 * 处理安卓返回键 
 */  
const defaultStateAction = AppNavigator.router.getStateForAction;  
AppNavigator.router.getStateForAction = (action,state) =>   
    if(state && action.type === NavigationActions.BACK && state.routes.length === 1)   
        if (lastBackPressed + 2000 < Date.now())   
            ToastAndroid.show(Constant.hint_exit,ToastAndroid.SHORT);  
            lastBackPressed = Date.now();  
            const routes = [...state.routes];  
            return   
                ...state,  
                ...state.routes,  
                index: routes.length - 1,  
            ;  
          
      
    return defaultStateAction(action,state);  
; 
  • 实现Android中界面跳转左右切换动画

react-navigation在android中默认的界面切换动画是上下。如何实现左右切换呢?很简单的配置即可:

import CardStackStyleInterpolator from 'react-navigation/src/views/CardStackStyleInterpolator';  

然后在StackNavigator的配置下添加如下代码:

transitionConfig:()=>(  
    screenInterpolator: CardStackStyleInterpolator.forHorizontal,  
) 
  • 解决快速点击多次跳转

当我们快速点击跳转时,会开启多个重复的界面,如何解决呢。其实在官方Git中也有提示,解决这个问题需要修改react-navigation源码:
找到scr文件夹中的addNavigationHelpers.js文件,替换为如下文本即可:

export default function<S: *>(navigation: NavigationProp<S, NavigationAction>)   
  // 添加点击判断  
  let debounce = true;  
  return   
      ...navigation,  
      goBack: (key?: ?string): boolean =>  
          navigation.dispatch(  
              NavigationActions.back(  
                  key: key === undefined ? navigation.state.key : key,  
              ),  
          ),  
      navigate: (routeName: string,  
                 params?: NavigationParams,  
                 action?: NavigationAction,): boolean =>   
          if (debounce)   
              debounce = false;  
              navigation.dispatch(  
                  NavigationActions.navigate(  
                      routeName,  
                      params,  
                      action,  
                  ),  
              );  
              setTimeout(  
                  () =>   
                      debounce = true;  
                  ,  
              500,  
              );  
              return true;  
            
          return false;  
      ,  
    /** 
     * For updating current route params. For example the nav bar title and 
     * buttons are based on the route params. 
     * This means `setParams` can be used to update nav bar for example. 
     */  
    setParams: (params: NavigationParams): boolean =>  
      navigation.dispatch(  
        NavigationActions.setParams(  
          params,  
          key: navigation.state.key,  
        ),  
      ),  
  ;  

欢迎关注我的公众号,一起交流学习!

以上是关于React-Native中导航组件react-navigation的使用的主要内容,如果未能解决你的问题,请参考以下文章

React-Native中导航组件react-navigation的使用

react-native:无法读取未定义的属性“导航”

React-native 组件缓存(或防止卸载)(react-navigation)

React-native 导航实验示例?

带有导航的 React-native ListView

react-native导航器 react navigation 介绍