在React Native
中,官方已经推荐使用react-navigation
来实现各个界面的跳转和不一样板块的切换。react-navigation
主要包括三个组件:react
StackNavigator
导航组件TabNavigator
切换组件DrawerNavigator
抽屉组件StackNavigator
用于实现各个页面之间的跳转,TabNavigator
用来实现同一个页面上不一样界面的切换,DrawerNavigator
能够实现侧滑的抽屉效果。android
StackNavigator
组件采用堆栈式的页面导航来实现各个界面跳转。它的构造函数:git
StackNavigator(RouteConfigs, StackNavigatorConfig)复制代码
有RouteConfigs
和StackNavigatorConfig
两个参数。api
RouteConfigs
参数表示各个页面路由配置,相似于android原生开发中的AndroidManifest.xml
,它是让导航器知道须要导航的路由对应的页面。数组
const RouteConfigs = {
Home: {
screen: HomePage,
navigationOptions: ({navigation}) => ({
title: '首页',
}),
},
Find: {
screen: FindPage,
navigationOptions: ({navigation}) => ({
title: '发现',
}),
},
Mine: {
screen: MinePage,
navigationOptions: ({navigation}) => ({
title: '个人',
}),
},
};复制代码
这里给导航器配置了三个页面,Home
、Find
、Mine
为路由名称,screen
属性值HomePage
、FindPage
、MinePage
为对应路由的页面。bash
navigationOptions
为对应路由页面的配置选项:app
title
- 能够做为头部标题headerTitle
,或者Tab标题tabBarLabel
header
- 自定义的头部组件,使用该属性后系统的头部组件会消失headerTitle
- 头部的标题,即页面的标题headerBackTitle
- 返回标题,默认为title
headerTruncatedBackTitle
- 返回标题不能显示时(好比返回标题太长了)显示此标题,默认为“Back”
headerRight
- 头部右边组件headerLeft
- 头部左边组件headerStyle
- 头部组件的样式headerTitleStyle
- 头部标题的样式headerBackTitleStyle
- 头部返回标题的样式headerTintColor
- 头部颜色headerPressColorAndroid
- Android 5.0
以上MD风格的波纹颜色gesturesEnabled
- 否能侧滑返回,iOS
默认true
,Android
默认false
StackNavigatorConfig
参数表示导航器的配置,包括导航器的初始页面、各个页面之间导航的动画、页面的配置选项等等:函数
const StackNavigatorConfig = {
initialRouteName: 'Home',
initialRouteParams: {initPara: '初始页面参数'},
navigationOptions: {
title: '标题',
headerTitleStyle: {fontSize: 18, color: '#666666'},
headerStyle: {height: 48, backgroundColor: '#fff'},
},
paths: 'page/main',
mode: 'card',
headerMode: 'screen',
cardStyle: {backgroundColor: "#ffffff"},
transitionConfig: (() => ({
screenInterpolator: CardStackStyleInterpolator.forHorizontal,
})),
onTransitionStart: (() => {
console.log('页面跳转动画开始');
}),
onTransitionEnd: (() => {
console.log('页面跳转动画结束');
}),
};复制代码
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
- 页面跳转动画一旦完成会立刻调用页面的配置选项navigationOptions
一般还能够在对应页面中去静态配置,好比在HomePage
页面中:字体
export default class HomePage extends Component {
// 配置页面导航选项
static navigationOptions = ({navigation}) => ({
title: 'HOME',
titleStyle: {color: '#ff00ff'},
headerStyle:{backgroundColor:'#000000'}
});
render() {
return (
<View></View>
)
};
}复制代码
一样地,在页面里面采用静态的方式配置navigationOptions
中的属性,会覆盖StackNavigator
构造函数中两个参数RouteConfigs
和StackNavigatorConfig
配置的navigationOptions
里面的对应属性。navigationOptions
中属性的优先级是:
页面中静态配置 > RouteConfigs
> StackNavigatorConfig
动画
有了RouteConfigs
和StackNavigatorConfig
两个参数,就能够构造出一个导航器组件StackNavigator
,直接引用该组件:
const Navigator = StackNavigator(RouteConfigs, StackNavigatorConfig);
export default class MainComponent extends Component {
render() {
return (
<Navigator/>
)
};
}复制代码
已经配置好导航器以及对应的路由页面了,可是要完成页面之间的跳转,还须要navigation
。
在导航器中的每个页面,都有navigation
属性,该属性有如下几个属性/方法:
navigate
- 跳转到其余页面state
- 当前页面导航器的状态setParams
- 更改路由的参数goBack
- 返回dispatch
- 发送一个action调用这个方法能够跳转到导航器中的其余页面,此方法有三个参数:
— routeName
导航器中配置的路由名称
— params
传递参数到下一个页面
— action
action
好比:this.props.navigation.navigate('Find', {param: 'i am the param'});
state
里面包含有传递过来的参数params
、key
、路由名称routeName
,打印log能够看获得:
{
params: { param: 'i am the param' },
key: 'id-1500546317301-1',
routeName: 'Mine'
}复制代码
更改当前页面路由的参数,好比能够用来更新头部的按钮或者标题。
componentDidMount() {
this.props.navigation.setParams({param:'i am the new param'})
}复制代码
回退,能够不传,也能够传参数,还能够传null
。
this.props.navigation.goBack(); // 回退到上一个页面
this.props.navigation.goBack(null); // 回退到任意一个页面
this.props.navigation.goBack('Home'); // 回退到Home页面复制代码
TabNavigator
,便是Tab选项卡,相似于原生android
中的TabLayout
,它的构造函数:
TabNavigator(RouteConfigs, TabNavigatorConfig)复制代码
api和StackNavigator
相似,参数RouteConfigs
是路由配置,参数TabNavigatorConfig
是Tab选项卡配置。
路由配置和StackNavigator
中是同样的,配置路由以及对应的screen
页面,navigationOptions
为对应路由页面的配置选项:
title
- Tab标题,可用做headerTitle
和tabBarLabel
回退标题tabBarVisible
- Tab的是否可见,没有设置的话默认为true
tabBarIcon
- Tab的icon组件,能够根据{focused: boolean, tintColor: string}
方法来返回一个icon组件tabBarLabel
- Tab中显示的标题字符串或者组件,也能够根据{ focused: boolean, tintColor: string }
方法返回一个组件tabBarComponent
- Tab选项卡组件,有TabBarBottom
和TabBarTop
两个值,在iOS中默认为TabBarBottom
,在Android中默认为TabBarTop
。
TabBarTop
- 在页面的顶部TabBarBottom
- 在页面的底部tabBarPosition
- Tab选项卡的位置,有 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的文字颜色activeBackgroundColor
- 选中Tab的背景颜色inactiveTintColor
- 未选中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);复制代码
在原生Android MD 风格里面不少app都会采用侧滑抽屉来作主页面的导航,利用DrawerNavigator
在RN中能够很方便来实现抽屉导航。
DrawerNavigator(RouteConfigs, DrawerNavigatorConfig)复制代码
和DrawerNavigator
的构造函数同样,参数配置也相似。
抽屉导航的路由配置RouteConfigs
,和TabNavigator
的路由配置彻底同样,screen
配置对应路由页面,navigationOptions
为对应页面的抽屉配置选项:
title
- 抽屉标题,和headerTitle
、drawerLabel
同样drawerLabel
- 标签字符串,或者自定义组件, 能够根据{ focused: boolean, tintColor: string }
函数来返回一个自定义组件做为标签drawerIcon
- 抽屉icon,能够根据{ focused: boolean, tintColor: string }
函数来返回一个自定义组件做为icon抽屉配置项属性:
drawerWidth
- 抽屉宽度,可使用Dimensions获取屏幕的宽度,动态计算drawerPosition
- 抽屉位置,能够是left
或者right
contentComponent
- 抽屉内容组件,能够自定义侧滑抽屉中的全部内容,默认为DrawerItems
contentOptions
- 用来配置抽屉内容的属性。当用来配置DrawerItems
是配置属性选项:
items
- 抽屉栏目的路由名称数组,能够被修改activeItemKey
- 当前选中页面的key idactiveTintColor
- 选中条目状态的文字颜色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);复制代码
源码:git.oschina.net/xiaojianjun… (index20.js、index21.js、index22.js)