入门:
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 />
);
}
}