以下是在 React Navigation 4.x 版本测试的,其他版本可能略有不同,望知晓
StackNavigator
基础导航类型,一个页面存储栈,栈内预置页面(Component
)组件,也可以预置由 TabNavigator
、 DrawerNavigator
、甚至是 StackNavigator
或其他自定义类型路由构建的组件组合。
1. 基本用法
import { createStackNavigator } from 'react-navigation-stack';
createStackNavigator(RouteConfigs, StackNavigatorConfig);
// ex:
createStackNavigator({
Home:{},
Settings: {},
...
}, {
initialRouteName:"",
defaultNavigationOptions:{}
....
})
2. RouteConfigs
预置的页面栈,用于后续导航,导航只能打开在这个栈内的组件。
可仅指定为组件
RouteConfigs = {
news: News,
video: Video
}
// 若 routeName 与组件名相同,可 es6 简写
RouteConfigs = {News, Video}
也可附带参数
RouteConfigs = {
news: {
screen: News,
path: 'people/:news_id',
navigationOptions: Object|Function
},
...
}
关于 path 的作用可参考 这篇文章,navigationOptions 的作用和解析下面会详解
3. StackNavigatorConfig
导航配置,这个值得一说,有很大的自由度,但并不是特别容易理解
{
// 默认首页的路由名,从 RouteConfigs 挑一个,默认会使用第一个,
// 但 js object 的顺序可能并不严格,建议手工设置
initialRouteName:String
// 初始路由参数,该参数可在所有页面内获取,不会对路由本身有影响
initialRouteParams:Object
// 初始路由的标志符,在导航函数中可以使用该参数
// 一般用不到,主要用 routeName
initialRouteKey:String
// 所有栈内页面的默认配置
// 每个页面都可以通过 navigationOptions 进行重置
// 有很多参数,下面会详解
defaultNavigationOptions:Object,
// 若路由本身作为一个页面组,放到另外一个路由的页面栈中
// 路由组缺省会使用上级 defaultNavigationOptions 配置
// 这里相当于把整个路由组作为一个页面,使用 navigationOptions 重置上级配置
navigationOptions:Object,
// 重置 RouteConfigs 参数中配置的页面 path,
paths:Object,
// 切换页面默认情况下会自动关闭已打开的键盘
// 若需要禁止这种行为,这里可以设置为 true
disableKeyboardHandling:Bool
// 页面头部(标题栏)模式
// float: iOS默认模式,头部和主体是分离的
// 这样在切换页面时,两个页面头部是渐隐渐现,主体是 左右滑入滑出
// android 也可使用该模式, 头部仍然是渐隐渐现, 主体则是 上下滑入滑出
// screen: android默认模式,头部和主体同在一个大的 dom 内
// 这样切换页面时,是整体移动的,上下滑入滑出的
// iOS 也可使用该模式, 整体是 左右滑入滑出
// none: 不需要头部
headerMode: 'float' | 'screen' | 'none'
// 是否在标题栏返回按钮的旁边显示 返回标题
// android 默认不显示 iOS 默认显示
headerBackTitleVisible:Bool
// 标题栏布局
// 指定标题是紧挨着返回键,还是在标题栏中居正中
// android 默认 left, iOS 默认 center
headerLayoutPreset:'left' | 'center'
// 在 headerMode 为 float 时生效,此时 header 是一个单独区域
// 用该参数设置页面切换时, 两个页面 header 的过渡效果
// fade-in-place: 旧 header 逐渐透明, 新 header 从透明逐渐显示
// uikit: 在拥有 fade-in-place 效果的同时, header 布局也有动态效果,
// 返回标题会从左侧移动到正中, 所以该效果要求
// 1.标题栏中显示返回标题 (headerBackTitleVisible=true)
// 2.标题栏中的标题为居中布局 (headerLayoutPreset=center)
// 加上 headerMode=float,可以看出,在默认配置下,该模式其实就是针对 iOS 设计的
// 事实上 iOS 原生 title 就是这个效果, 但该模式对标题栏布局要求比较严格,
// 除非是标题栏完全没有进行自定义, 否则不建议使用该模式
headerTransitionPreset: 'fade-in-place' | 'uikit'
// 页面模式,需配合 headerMode 理解
// card: 即默认模式
// modal: iOS专享模式,card 模式下,iOS 默认为 float 头部,
// 但如果这里设置为 modal 模式,iOS 页面会转为近似于头部为 screen 的效果
// 即头部和主体是在同一个 dom 内, 不同的是, modal 打开新页面, 是从底部滑入的
// 比如该模式可以将 StackNavigator 和一个单独的 页面嵌套, 做一个欢迎页
// 欢迎页关闭后, 即进入了正常模式下的 StackNavigator
// 不过也可以使用其他办法替代,个人感觉这个模式略微鸡肋
mode:'card' | 'modal'
// 页面样式扩展,有点类似于 html css 中对 body 进行 css 定义
cardStyle:Object,
// 两个页面切换时, 下层页面是否覆盖上一个半透明黑色遮罩,默认为 false
cardOverlayEnabled:Bool
// 两个页面切换时, 上层页面是否显示左侧边缘阴影,默认为 true
// 该效果仅针对 iOS,左右划入滑入,android 是上下滑入滑出的
// 当前版本,即使 android 也改用左右滑入模式, 该配置也不生效
// 因为 android 不支持 shadow style,虽然在 android 可通过 elevation 实现阴影,
// 但功能非常弱,无法满足要求,或者借助 react-native-shadow 这样的三方组件
// 但成本都不算低, 所以 React Navigation 目前干脆没支持 android 阴影
cardShadowEnabled:Bool
// 自定义页面切换效果,这里可以实现 android 左右滑入滑出以及阴影等
// 设置可以完全实现为其他效果,下面会详解
transitionConfig: Function
// 页面切换开始/结束时的回调函数
onTransitionStart:Function
onTransitionEnd:Function
}
4. StackNavigatorConfig.(defaultNavigationOptions
navigationOptions
)
针对页面的配置,可以通过 defaultNavigationOptions
设置一个默认的,也可以通过 navigationOptions
为每个页面单独配置
使用方法
// 方式一
createStackNavigator({
News:{
screen:News,
navigationOptions:{
title:"新闻"
}
},
Video:{
screen:Video,
},
...
}, {
defaultNavigationOptions:{
title:"默认标题"
}
....
})
// 方式二
createStackNavigator({
News:{
screen:News,
navigationOptions: (nav) => {
return {
title:"新闻"
}
}
},
Video:{
screen:Video,
},
...
}, {
defaultNavigationOptions:(nav) => {
return {
title:"默认标题"
}
}
....
})
// 即:可以直接通过 Object 指定,也可以使用函数,
// 当配置需要导航器内部的一些变量或方法时,使用函数就比较方便了
这样使用 navigationOptions
来配置单独页面,过于集中了,还有另外一种方法配置,个人推荐使用下面的方式,比如在 News
页面内部
class News extends React.Component {
static navigationOptions = {
title:'新闻'
}
....
}
或
class News extends React.Component {
static navigationOptions = (nav) => {
return {
title:"新闻"
}
}
....
}
// 这种方案避免了每次修改某一个页面,都要去修改调用方法,耦合度低
可配置项
defaultNavigationOptions | navigationOptions :{
// 完全自定义 header,下面关于 header 的 props 也会传递过来以供使用
header: React Element | Function
// 默认 header 组件使用了 SafeAreaView 进行包裹,该设置是传递给 SafeAreaView 的
// 详情: https://reactnavigation.org/docs/zh-Hans/handling-iphonex.html
headerForceInset:Object
// 对 默认 header 组件样式进行扩充
headerStyle:Object
// header 字体默认颜色
headerTintColor:String
// 是否将 header 设置为透明
headerTransparent:Bool
// 自定义一个组件放置在 header 正下方
// 比如结合 headerTransparent=true 弄一个毛玻璃效果组件放在下面
// 就有了一个毛玻璃效果的标题栏
headerBackground:React Element | React Component
// 当两个页面切换时, 指定自定义 headerBackground 的过渡效果
headerBackgroundTransitionPreset: 'toggle' | 'fade' | 'translate'
// 缺省标题
// 作为 headerTitle 的 缺省值
// 在 TabNavigator 还作为 tabBarLabel 的 缺省值
// 在 DrawerNavigator 还作为 drawerLabel 的 缺省值
title:String
// 标题
// 可自定义组件,也可直接指定为 string (使用默认标题组件)
headerTitle:String | React Element | React Component
// headerTitle 为 string
// 对默认标题组件进行样式扩充
headerTitleStyle:Object
// 若 headerTitle 为自定义组件
// 会被放到一个包裹层中,可对包裹层进行样式扩充
headerTitleContainerStyle:Object
// 返回按钮
headerBackImage: React Element | Component
// 返回标题
// 在 StackNavigatorConfig.headerBackTitleVisible 配置为 true 的情况下
// 该标题将会显示在下一个页面的返回键旁边, 未指定则使用 headerTitle
// 若不希望显示,可设置为 null
headerBackTitle:String
// 返回短标题
// 在下一个页面的标题栏拥挤时, 会调用这个短标题作为返回标题
headerTruncatedBackTitle:String
// 针对 android 5.0 以上系统
// 设置点击返回键(包裹了返回按钮和返回标题)时的水波纹颜色
headerPressColorAndroid:String,
// 对返回标题进行样式扩充
headerBackTitleStyle:Object
// 标题中文字是否依照系统字体大小进行缩放
headerTitleAllowFontScaling:Bool
// 返回标题是否依照系统字体大小进行缩放
headerBackAllowFontScaling:Bool
// 标题栏左侧组件
// 默认为 返回按钮 和 可能的返回标题
headerLeft: React Element | Component
// 自定义 headerLeft 会被放进一个包裹层中
// 可对这个包裹层进行样式扩充
headerLeftContainerStyle:Object
// 标题栏右侧组件,默认为空
headerRight: React Element | Component
// 自定义 headerRight 会被放进一个包裹层中
// 可对这个包裹层进行样式扩充
headerRightContainerStyle:Object
// 是否可使用手势返回到上一个页面
// iOS 默认为 true, android 为 false
gesturesEnabled:Bool
// 手势方向
// default 为从左向右滑来返回到上个页面, inverted 相反方向
gestureDirection:'default' | 'inverted'
// 滑动距离超过指定值才会返回到上一个页面, 否则仍弹回到当前页
// 可设置 手机为 竖屏和横屏 情况的阈值距离
gestureResponseDistance: {horizontal: 25, vertical:135}
// 自定义参数, 可在页面中通过 navigation.getParam 获取
params:Object
}
引申出一个小技巧,默认标题栏组成部分: 返回按钮 / 返回标题 / 标题,分别设置三者的颜色
{
// 三个组件都变成蓝色了
headerTintColor:'blue'
// 把返回标题改成 绿色了
headerBackTitleStyle:{.
color:'green'
}
// 把标题改成黑色了
headerTitleStyle: {
color:'black'
}
// 没有单独设置 返回按钮 颜色的选项, 但可以通过这种方法, 控制三者使用不同颜色
}
5. StackNavigatorConfig.transitionConfig
定义两个页面切换的过渡效果,自定义函数应返回 TransitionConfig 格式的数据,并不要求是完整的,有缺失的情况下,会自动使用自带的 StackViewTransitionConfigs 进行补充,可仔细看一下该文件,其中定义的方法可作为自己写的参考,简单的说一下使用方法
import {StackViewTransitionConfigs, createStackNavigator} from 'react-navigation-stack';
function TransitionConfiguration(transitionProps, prevTransitionProps, isModal){
// 不显示动画效果
return StackViewTransitionConfigs.NoAnimation;
// android / iOS 都使用左右滑动进入的过渡效果
return StackViewTransitionConfigs.SlideFromRightIOS;
// 保持默认效果,但修改过渡动画的时长
return {
transitionSpec: {
duration: 2000,
}
}
}
createStackNavigator({
...
}, {
defaultNavigationOptions:{
transitionConfig:TransitionConfiguration,
}
})
Tab navigation
该导航类型有 createBottomTabNavigator、createMaterialBottomTabNavigator、createMaterialTopTabNavigator,国内大部分 app 使用的都是 BottomTabNavigator 类型,鉴于这种情况,用户习惯已经培养成这样了,所以只针对 BottomTabNavigator 做个说明,其他两个基本类似
1. 基本用法
import { createBottomTabNavigator } from 'react-navigation-tabs';
createBottomTabNavigator(RouteConfigs, TabNavigatorConfig);
// ex:
createBottomTabNavigator({
Home:{},
Settings: {},
...
}, {
initialRouteName:"",
defaultNavigationOptions:{}
....
})
2. RouteConfigs
配置 tabs 的每个页面,参考上面 StackNavigator 的 RouteConfigs,与其相同
3. TabNavigatorConfig
针对 Tab Navigator 的配置
{
// 默认载入选项卡的 routeName
initialRouteName:String
// 通过 routeName 数组设置选项卡显示顺序
order: Array
// 重置 RouteConfigs 中的 path
paths:Object
// 是否懒加载, 即在进入选项卡页面时,才进行渲染
lazy:Bool
// 当前显示页是选项卡,android 下点击物理返回键的响应方式 (默认为 initialRoute)
// initialRoute: 返回到 initialRouteName 定义的初始选项卡,若已在这个选项卡,则退出 app
// order: 按照 order 配置的(或 RouteConfigs 顺序) 逐个返回,若当前在 order 中的第一个,退出
// history: 返回上一个浏览的选项卡 (实测没效果,与 none 相同)
// none: 无返回,直接退出
backBehavior:'initialRoute' | 'order' | 'history' | 'none'
// 切换离开屏幕时,是否重置所有嵌套导航器的状态
// 这个我没用到,所以也没整太明白,看官方说明
// 应该是 RouteConfigs 中设置的组件本身又是一个 导航组
// 用这个参数来设定是否缓存导航组内的 组件 状态
resetOnBlur:Bool
// 自定义 TabBar 组件,替换默认的
// https://github.com/react-navigation/tabs/blob/master/src/views/BottomTabBar.tsx
tabBarComponent: React Component
// 针对 默认 tabBarComponent 视觉相关的配置,下面详解
tabBarOptions:Object
// 针对 默认 tabBarComponent 功能相关的配置,下面详解
defaultNavigationOptions:Object
// 当整个 TabNavigator 作为一个组件嵌套在另外一个路由中
// 设置 整体作为一个子页面的 自定义配置
navigationOptions:Object,
}
4. TabNavigatorConfig.tabBarOptions
与 视觉相关的配置
tabBarOptions: {
// 当前激活的选项卡, 前景色/背景色
activeTintColor:String
activeBackgroundColor:String
// 未激活的选项卡 前景色/背景色
inactiveTintColor:String
inactiveBackgroundColor:String
// 对 整个 tabbar 的样式进行扩充
style:Object,
// 选项卡是否显示 icon 图标
showIcon:Bool
// 选项卡是否显示 label 文字
showLabel:Bool
// label 文字是否依照系统字体大小进行缩放
allowFontScaling:Bool
// icon/label 排列方式, 默认为 below-icon, 即 label 文字在 icon 下面
// 设置为 beside-icon 则转为左右排列, 也可以通过函数方式返回
// Function({ deviceOrientation }) 参数会传递当前的屏幕方向
labelPosition:'beside-icon' | 'below-icon' | Function
// 设备横屏状态下,是否将 icon/label 转为左右排列
// 默认情况下, 只有在 iOS>=11 的 iPad 为 true, 其他都为 false
// 若自定义了 labelPosition, 则以 labelPosition 为准
adaptive:Bool
// 对 tabbar 样式进行扩充
style:Object
// 对 tabbar 上 单个选项卡组件 进行样式扩充
tabStyle:Object,
// 对 label 文字组件的样式进行扩充
labelStyle:Object,
// 默认 tabbar 组件使用了 SafeAreaView 进行包裹,该设置是传递给 SafeAreaView 的
// 详情: https://reactnavigation.org/docs/zh-Hans/handling-iphonex.html
safeAreaInset:Object
// 当系统键盘打开时, 是否隐藏 tabbar, 默认 false
keyboardHidesTabBar:Bool
}
5. TabNavigatorConfig.(defaultNavigationOptions
navigationOptions
)
使用方法可参考上面 StackNavigatorConfig.(defaultNavigationOptions
navigationOptions
)
具体参数如下
{
// 是否显示 tabBar, 若有那种 期望作为 tab screen 的页面,但又不希望显示在 tab bar 上面
// 可以通过这个设置, 很明显, 该参数应该放到具体页面的 navigationOptions 中
// 而不应放到 defaultNavigationOptions 中,否则岂不是都不显示了
tabBarVisible:Bool
// 自定义 tab bar 中单个 item 选项卡的组件
// 该组件应该包裹 icon 和 label,可参考:
// https://github.com/react-navigation/tabs/blob/master/src/views/BottomTabBar.tsx#L30
tabBarButtonComponent:React Component
// 通过函数返回 icon 图标, ex:
// Function = ({focused: boolean, horizontal: boolean, tintColor: string}) => {
// return <Image ../>
// }
tabBarIcon:Function
// label 文字, 可直接指定为 字符串 或 rn 组件
// 也可定义为一个函数, 函数必须返回为组件(其实我认为这个不太合理,应该接受文字返回更好)
tabBarLabel: String | React Component | Function
// 标题,会作为 tabBarLabel 的 fallabck
// 也会作为 headerTitle 的 fallback
title:String
// 选项卡点击时的回调函数,
// 注意:自定义了这个,需自行处理跳转
tabBarOnPress:Function
// 长按 选项卡 的回调函数
tabBarOnLongPress:Function
// 测试id
tabBarTestID:String
// 无障碍文字,可参考:
// https://reactnative.cn/docs/accessibility/
tabBarAccessibilityLabel:String
}
网友评论