react-navigation3.0版本的使用详解

入门:

React Navigation诞生于React Native社区需要一个由javascript编写的扩展且易于使用的导航解决方案。目前react-navigation已经更新到3.x版本了。如果对react-navigation不了解的可以先看React Native Express(http://www.reactnativeexpress.com/)前4章

什么是导航器:

导航器可以看作是一个普通的React组件,可以通过导航器来定义APP的导航结构,导航器还可以渲染通用元素,比如配置标题栏和选项卡栏,在React-navigation中有一下三种类型的导航器:createStackNavigator,createSwitchNavigator,createDrawerNavigator,createBottomTabNavigator,createMaterialBottomTabNavigator,createMaterialTopTabNavigator等,详情请看官网:https://reactnavigation.org/docs/en/material-top-tab-navigator.html

两个与导航器相关的概念:

  • navigation prop(屏幕导航属性):通过navigation可以完成屏幕之间的调度操作
  • navigationOptions(屏幕导航选项):通过navigationOptions可以定制导航器显示屏幕的方式(头部标题,选项卡标签等)

Navigation prop 详解

当导航器中的屏幕被打开时,会收到一个navigation prop,navigation包含以下功能

  • navigate - 转跳到其他界面
class ProfileScreen extends React.Component {
  render() {
    return (
      <Button
        onPress={()=>navigation('Profile', {name: '稻城'})}
        title="Set title name to '稻城'"
      />
    );
  }
}
  • goback - 关闭当前界面
class ProfileScreen extends React.Component {
  render() {
    return (
      <Button
        onPress={goBack()}
        title="Set title name to '稻城'"
      />
    );
  }
}
  • addListener - 订阅导航生命周期的更新
  • isFocused - 一个函数返回true或false,查询屏幕是否获取焦点
  • state - 屏幕当前的state
class ProfileScreen extends React.Component {
  render() {
    const params = this.props.navigation.state
    return <Text>Name: {params.name}</Text>;
  }
}

  • setParams - 改变路由的params
class ProfileScreen extends React.Component {
  render() {
    return (
      <Button
        onPress={() => this.props.navigation.setParams({ name: 'Lucy' })}
        title="Set title name to '稻城'"
      />
    );
  }
}
  • dispatch - 向路由发送一个action
import { NavigationActions } from 'react-navigation';

const navigateAction = 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(navigateAction); 
  • dangerouslyGetParent - 返回父导航器的函数

navigation有一下几种方式:

  • push - 将新路由推入堆栈
navigation.push(routeName, params, action)
  • pop - 回到堆栈中
navigation.pop(n)  //n为在路由堆栈中的第几个screen
  • popToTop - 转到堆栈顶部
navigation.popToTop()
  • replace - 用新的路由替换当前路由
navigation.replace(routeName, params, action)
  • reset - 删除所有的navigation state并且使用这个reset的代替
navigation.reset([NavigationActions.navigate({ routeName: 'Profile' })], 0
  • dismiss - 关闭当前堆栈
navigation.dismiss()

createStackNavigator的使用

为APP提供一种在屏幕之间转换的方式,其中每个新屏幕都放置在堆栈顶部。默认情况下,堆栈导航器配置为具有熟悉的iOS和Android外观:新的屏幕从iOS右侧滑入,从Android底部淡入。在iOS上,堆栈导航器也可以配置为模式样式,屏幕从底部滑入。

API的定义

createStackNavigator(RouteConfigs, StackNavigatorConfig);

RouteConfigs

route configs对象是从路由名称到路由配置的映射,它告诉导航器为该路由提供什么。

createStackNavigator({
  // For each screen that you can navigate to, create a new entry like this:
  Profile: {
    // `ProfileScreen` is a React component that will be the main content of the screen.
    screen: ProfileScreen,
    // When `ProfileScreen` is loaded by the StackNavigator, it will be given a `navigation` prop.

    // Optional: When deep linking or using react-navigation in a web app, this path is used:
    path: 'people/:name',
    // The action and route params are extracted from the path.

    // Optional: Override the `navigationOptions` for the screen
    navigationOptions: ({ navigation }) => ({
      title: `${navigation.state.params.name}'s Profile'`,
    }),
  },

  ...MyOtherRoutes,
});
StackNavigatorConfig

路由器的选项

  • initialRouteName - 设置堆栈的默认屏幕。必须匹配路由配置中的一个键
  • initialRouteParams - 初始路线的参数
  • initialRouteKey - 初始路由的可选标识符
  • defaultNavigationOptions - 用于屏幕的默认导航选项
  • paths - 路径配置中设置的路径的覆盖映射

视觉选项

  • mode - 定义渲染和过渡的样式:
    • card - 使用标准的iOS和Android屏幕过渡。这是默认值。
    • modal - 使屏幕从底部滑入,这是一种常见的iOS模式。仅适用于iOS,对Android没有影响。
  • headerMode - 指定标头的呈现方式:
    • float - 渲染单个标题,保持在顶部,并在屏幕更改时设置动画。这是iOS上的常见模式。
    • screen - 每个屏幕都附有一个标题,标题与屏幕一起淡入淡出。这是Android上的常见模式。
    • none - 不会呈现标题。
  • headerBackTitleVisible- 提供了合理的默认值,以确定后退按钮标题是否可见,但如果要覆盖可以使用true或false在此选项中。
  • headerTransitionPreset- 指定headerMode: float启用时标头应如何从一个屏幕转换到另一个屏幕。
    • fade-in-place - 标题组件交叉淡入淡出而不移动,类似于iOS的Twitter,Instagram和Facebook应用程序。这是默认值。
    • uikit - iOS的默认行为的近似值。
  • headerLayoutPreset - 指定如何布置标题组件。
    • left - 将标题锚定在左侧,靠近后退按钮或其他左侧组件。这是Android上的默认设置。在iOS上使用时,隐藏标题后退标题。左侧组件中的内容将溢出标题下方,如果您需要调整此内容,则可以使用headerLeftContainerStyle和headerTitleContainerStyle。此外,此对齐与此不兼容headerTransitionPreset: 'uikit'。
    • center - 将标题居中,这是iOS上的默认设置。
  • cardStyle - 使用此prop可以覆盖或扩展堆栈中单个卡的默认样式。
  • cardShadowEnabled - 使用此道具在过渡期间显示可见阴影。默认为true
    cardOverlayEnabled - 使用此prop可在转换期间显示可见的堆栈卡覆盖。默认为false。
  • transitionConfig- 返回与默认屏幕转换合并的对象的函数(在类型定义中查看TransitionConfig )。提供的函数将传递以下参数:
    • transitionProps - 为新屏幕过渡道具。
    • prevTransitionProps - 转换旧屏幕的道具。
    • isModal - 布尔值,指定屏幕是否为模态。
  • onTransitionStart - 卡转换动画即将开始时要调用的函数。
  • onTransitionEnd - 卡过渡动画完成后要调用的函数。
  • transparentCard- 实验 - 支持将堆栈中的所有卡片保持可见并添加透明背景而不是白色背景。这对于实现模式对话框很有用,其中前一个场景仍应在当前场景下可见。
navigationOptions 用于导航器内的屏幕导航选项
  • title - 可用作后备的字符串headerTitle。此外,将用作tabBarLabel(如果嵌套在TabNavigator中)或drawerLabel(如果嵌套在DrawerNavigator中)的后备。
  • header - React Element或给定HeaderProps返回React元素的函数,显示为标题。设置为null隐藏标题。
  • headerTitle - 标题使用的字符串,反应元素或反应组件。默认为场景title。当使用的成分,它接收allowFontScaling,style和children道具。传递标题字符串children。
  • headerBackImage - React Element或Component在标题的后退按钮中显示自定义图像。使用组件时,它在渲染(tintColor,title)时会收到许多道具。默认为带有react-navigation/views/assets/back-icon.png后方图像源的图像组件,后者是平台的默认后退图标图像(iOS上的V形符号和Android上的箭头)。
  • headerRight - React Element显示在标题的右侧。
  • headerLeft - React元素或组件显示在标题的左侧。当使用的成分,它接收到一个数道具呈现时(onPress,title,titleStyle和更多-检查Header.js完整的列表)。
  • headerStyle - 标题的样式对象
  • .....还有好多就不一一列举了,感兴趣就去官网看看吧(https://reactnavigation.org/docs/en/stack-navigator.html)

createBottomTabNavigator的使用

屏幕底部的一个简单标签栏,可让您在不同的路线之间切换。路由被懒惰地初始化 - 它们的屏幕组件在首次聚焦之前不会被安装

API的定义

createBottomTabNavigator(RouteConfigs, BottomTabNavigatorConfig);

RouteConfigs

route configs对象是从路由名称到路由配置的映射,它告诉导航器为该路由提供什么,请参阅堆栈导航器中的示例。

BottomTabNavigatorConfig
  • initialRouteName - 首次加载时初始制表符路径的routeName。
  • order - routeNames数组,用于定义选项卡的顺序。
  • paths - 提供routeName到path config的映射,该映射覆盖routeConfigs中设置的路径。
  • backBehavior - 后退按钮是否会导致选项卡切换到初始选项卡?如果是,则设置为initialRoute,否则none。默认为initialRoute行为。
  • tabBarComponent - 可选,覆盖用作标签栏的组件。
  • tabBarOptions - 具有以下属性的对象:
    • activeTintColor - 活动选项卡的标签和图标颜色。
    • activeBackgroundColor - 活动选项卡的背景颜色。
    • inactiveTintColor - 非活动选项卡的标签和图标颜色。
    • inactiveBackgroundColor - 非活动选项卡的背景颜色。
    • showLabel - 是否为标签显示标签,默认为true。
    • showIcon - 是否显示选项卡的图标,默认为true。
    • style - 标签栏的样式对象。
      -labelStyle - 选项卡标签的样式对象。
    • tabStyle - 选项卡的样式对象。
      -allowFontScaling - 标签字体是否应缩放以符合“文本大小”辅助功能设置,默认为true。
    • safeAreaInset- 覆盖forceInset道具<SafeAreaView>。默认为{ bottom: 'always', top: 'never' }。可用键top | bottom | left | right随值提供'always' | 'never'。
tabBarOptions: {
  activeTintColor: '#e91e63',
  labelStyle: {
    fontSize: 12,
  },
  style: {
    backgroundColor: 'blue',
  },
}
navigationOptions 用于导航器内的屏幕导航选项
  • title - 通用标题可以用作备用headerTitle和tabBarLabel。
  • tabBarVisible - true或false显示或隐藏标签栏,如果未设置则默认为true。
  • tabBarIcon - React Element或给定{ focused: boolean, horizontal: boolean, tintColor: string }返回React.Node 的函数,以显示在选项卡栏中。horizontal是true当设备处于风景和false肖像时。每当设备方向改变时,都会重新呈现图标。
  • tabBarLabel - 标签栏或React元素中显示的选项卡的标题字符串或给定的函数{ focused: boolean, tintColor: string }返回React.Node,以显示在选项卡栏中。未定义时,使用场景title。要隐藏,请参阅tabBarOptions.showLabel上一节。
  • tabBarButtonComponent - 包含图标,标签和实现的React Component onPress。默认值是一个包装器TouchableWithoutFeedback,使其行为与其他触摸器相同。tabBarButtonComponent: TouchableOpacity会TouchableOpacity改用。
  • .....还有好多就不一一列举了,感兴趣就去官网看看吧(https://reactnavigation.org/docs/en/bottom-tab-navigator.html)

实战部分

基于react-navigation3.0最新的版本实现stack in tabs 和stack over tabs 两种效果

Stack in tabs

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 *
 * @format
 * @flow
 */

import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View} from 'react-native';
import {
  createStackNavigator,
  createBottomTabNavigator,
  createAppContainer,
  createMaterialTopTabNavigator,
} from 'react-navigation'
import { HomeTab, FindTab } from './Router/routers'


const CreateTab = createMaterialTopTabNavigator({
  Home: {
    screen: HomeTab,
    navigationOptions: () => ({
      tabBarLabel: '首页',
    })
  },
  Find: {
    screen: FindTab,
    navigationOptions: () => ({
      tabBarLabel: '发现',
    })
  }
}, {
  initialRouteName: 'Find',
  tabBarPosition: 'bottom',
  lazy: true,
  swipeEnabled: false,
  tabBarOptions: {
    activeTintColor: 'red',
    style: {
      backgroundColor: '#fff',
    },
  }
})

const CreaterTab = createAppContainer(CreateTab)

export default class App extends Component {
  render() {
    return (
      <CreaterTab />
    );
  }
}

Stack over tabs

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 *
 * @format
 * @flow
 */

import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View} from 'react-native';
import {
  createStackNavigator,
  createBottomTabNavigator,
  createAppContainer,
  createMaterialTopTabNavigator,
} from 'react-navigation'
import { HomeTab, FindTab } from './Router/routers'
import WebScreen from './screen/web/webScreen'


const CreateTab = createMaterialTopTabNavigator({
  Home: {
    screen: HomeTab,
    navigationOptions: () => ({
      tabBarLabel: '首页',
    })
  },
  Find: {
    screen: FindTab,
    navigationOptions: () => ({
      tabBarLabel: '发现',
    })
  }
}, {
  initialRouteName: 'Find',
  tabBarPosition: 'bottom',
  lazy: true,
  swipeEnabled: true,
  tabBarOptions: {
    activeTintColor: 'red',
    style: {
      backgroundColor: '#fff',
    },
  }
})

const StacksOverTabs = createStackNavigator({
  Root: {
    screen: CreateTab,
    navigationOptions: {
        header: () => null, 
    }
  },
  WebView: {
        screen: WebScreen,
        navigationOptions: {
            title: '熊孩宝测试',
        },
    }
});

const StacksOverTab = createAppContainer(StacksOverTabs)

export default class App extends Component {
  render() {
    return (
      <StacksOverTab />
    );
  }
}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,233评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,013评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,030评论 0 241
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,827评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,221评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,542评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,814评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,513评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,225评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,497评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,998评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,342评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,986评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,812评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,560评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,461评论 2 266

推荐阅读更多精彩内容

  • react-native.jpeg 本文是基于最新的react-navigation^2.9.1来书写的。 如果遇...
    挂着铃铛的兔阅读 220,711评论 131 298
  • react-navigation导航组件使用详解 注意了,如果有小伙伴们发现运行作者提供的react-naviga...
    光强_上海阅读 23,294评论 39 103
  • 本文是基于最新的react-navigation^2.9.1来书写的。 要感谢挂着铃铛的兔看到一篇不错的介绍,这里...
    HT_Jonson阅读 880评论 0 52
  • 我已不记得这本书是从何时进入了我的书单,又从何时摆在了我的书架上,我读的这版是2016年2月份的第6次印刷版,可见...
    完颜洋洋阅读 279评论 0 0
  • 你从来就是小众的,落得个清闲,浮生一把蒲扇,便散开了云遮雾绕; 你从来就是小众的,落得个不羁,来世一壶浊酒,便迷幻...
    达马Fumer阅读 390评论 0 0