在很久之前,RN中文网说推荐用react-navigation替代navigator作为新的导航库,从RN 0.43版本开始,官方就已经停止维护Navigator了,所以强烈建议大家迁移到新的react-navigation库,而且新的导航库无论从性能还是易用性上都要大大好于老的Navigator!
附上英文文档地址,
这个是我自己写的导航例子:https://github.com/lizhuoyuan/React_Navigation
推荐直接看事例,注释清楚.逻辑较为容易理解
接下来我们看react-navigation的使用。
一 StackNavigator
1.下载和安装
在项目根目录执行:
npm install --save react-navigation
2.在js文件中引入我们需要的组件
3.开始使用
import Home from './Home'; import Mains from './Second' const App = StackNavigator({ Home: {screen: Home}, Chat: {screen: Second}, Two: {screen: Mains} }); export default App;
export default class Home extends React.Component {
static navigationOptions = {
title: 'Welcome',
};
会在标题栏显示 Welcome的字样。
使用navigate()方法来执行跳转
render() {
const {navigate} = this.props.navigation;
let user = {'name': 'zy', age: 18}
return (
<View>
<Text onPress={() => navigate('Chat', {user:user})}>Home</Text>
</View>
)
}
}
render() {
const {navigate} = this.props.navigation;
let {params} = this.props.navigation.state;
return (
<View>
<Text>Second {params.user.name}</Text>
</View>
)
}
class Second extends React.Component {
static navigationOptions = ({navigation}) => ({
title: ` ${navigation.state.params.user.name}`, //前一个页面传来的对象的name属性
})
render() {
const {navigate} = this.props.navigation;
let {params} = this.props.navigation.state;
return (
<View>
<Text onPress={() => navigate('Home')}>Second {params.user.name}</Text>
</View>
)
}
}
class Three extends React.Component {
static navigationOptions = ({navigation}) => ({
title: ` ${navigation.state.params.user.age}`,
})
render() {
const {navigate} = this.props.navigation;
let {params} = this.props.navigation.state;
var name = params.name;
return (
<View>
<Text>three : {params.user.age}</Text>
</View>
)
}
}
const MainSceen = TabNavigator({
l1: {screen: Second},
l2: {screen: Three}
})
export default MainSceen;
const App = StackNavigator({
Home: {screen: Home},
// Chat: {screen: Second},
Two: {screen: Mains}
});
static navigationOptions = ({navigation}) => ({
title: ` ${navigation.state.params.user.name}`,
headerRight:<Button title={'标题'}/>
})
当然你也可以换成其他组件,也可以添加点击事件等等。也可以一起配。
const App = StackNavigator({ Home: { screen: Home, navigationOptions: { headerTitle: 'Home', //headerTitle和title效果相同 设置导航栏标题,推荐用这个方法 headerTitleStyle: {color: 'red', backgroundColor: 'white', alignSelf: 'center'}, //标题栏文字样式 设置居中 headerStyle: {backgroundColor: 'green'}, //导航栏的样式 //header: null //隐藏导航栏 headerRight: <Text onPress={() => { alert('i am right'); } }>right</Text>, //标题栏左右的按钮 headerLeft: <Text style={{marginLeft: 10}}>left</Text>, //最好定义在组件内部 } }, First: { screen: First, navigationOptions: ({navigation}) => ({ headerTitle: 'i am first', headerStyle: {backgroundColor: 'green'}, //导航栏的样式 headerTitleStyle: {color: 'red', alignSelf: 'center', backgroundColor: 'white'}, headerLeft: <Button title={'go back'} onPress={() => { navigation.goBack(); }}/>, }) }, Second: { screen: Second, navigationOptions: {} }, Tab: { screen: Tab, navigationOptions: { title: 'Tab', } }, });
StackNavigatorConfig
路由器的选项:
initialRouteName
- 设置堆栈的默认屏幕。必须匹配路由配置中的一个密钥。也就是已有的路由名字initialRouteParams
- 初始路线的参数navigationOptions
- 用于屏幕的默认导航选项paths
- 路由配置中设置的路径的覆盖映射
视觉选项:
mode
- 定义渲染和转换的样式:card
- 使用标准的iOS和Android屏幕转换。这是默认值。modal
- 使屏幕从底部滑入,这是普通的iOS模式。只适用于iOS,对Android无影响。
headerMode
- 指定标题应如何呈现:float
- 渲染一个保持在顶部的标题,并且随着画面的改变而呈现动画。这是iOS上的常见模式。screen
- 每个屏幕都有一个标题,标题与屏幕一起淡入淡出。这是Android上的常见模式。none
- 不会显示标题。
cardStyle
- 使用此支路覆盖或扩展堆叠中单个卡的默认样式。transitionConfig
- 返回覆盖默认屏幕转换的对象的功能。onTransitionStart
- 卡转换动画即将开始时调用的功能。onTransitionEnd
- 卡转换动画完成后要调用的功能。
title
串可以用作回退和headerTitle
tabBarLabel
header
React元素或给定的函数返回一个React元素,以显示为标题。设置隐藏标题。HeaderProps
null
headerTitle
标题使用的字符串或React元素。默认为场景title
headerBackTitle
iOS上的后退按钮使用的标题字符串或禁用标签。默认为场景null
title
headerTruncatedBackTitle
当返回按钮不适合屏幕时使用的标题字符串。默认。headerBackTitle
"Back"
headerRight
反应元素显示在标题的右侧
headerLeft
反应元素显示在标题的左侧
headerStyle
标题的样式对象
headerTitleStyle
标题组件的样式对象
headerBackTitleStyle
样式对象为后面的标题
headerTintColor
标题颜色
headerPressColorAndroid
颜色纹理(Android> = 5.0)
gesturesEnabled
#
是否可以使用手势关闭此屏幕。在iOS上默认为true,在Android上为false。
二. TabNavigator
1.引入组件
2.开始使用
/** * Sample React Native App * https://github.com/facebook/react-native * @flow */ import React from 'react'; import {Image,} from 'react-native'; import {TabNavigator} from 'react-navigation'; import HomePage from './app/home/HomePage'; import More from './app/more/More'; import MePage from './app/mepage/Me'; const App = TabNavigator({ HomePage: { screen: HomePage, navigationOptions: { tabBarLabel: '首页', //若不设置,则以key为标题 tabBarVisible: true, //是否隐藏标签栏。默认不隐藏(true),该选项卡激活时生效 tabBarIcon: ({tintColor}) => (<Image style={{height: 30, resizeMode: 'contain', tintColor: tintColor}} source={require('./img/ic_launcher.png')}/>) }, }, More: { screen: More, navigationOptions: { // tabBarLabel: '首页', tabBarVisible: true, //是否隐藏标签栏。默认不隐藏(true),该选项卡激活时生效 tabBarIcon: ({tintColor}) => (<Image style={{height: 30, resizeMode: 'contain', tintColor: tintColor}} source={require('./img/ic_launcher.png')}/>) }, }, MePage: { screen: MePage, navigationOptions: { // tabBarLabel: '首页', tabBarVisible: true, //是否隐藏标签栏。默认不隐藏(true),该选项卡激活时生效 tabBarIcon: ({tintColor}) => (<Image style={{height: 30, resizeMode: 'contain', tintColor: tintColor}} source={require('./img/ic_launcher.png')}/>) }, }, }, { tabBarPosition: 'bottom', //设置tabbar的位置,iOS默认在底部,安卓默认在顶部。(属性值:'top','bottom') swipeEnabled: true, //是否允许在标签之间滑动 animationEnabled: false, //是否在更改标签时显示动画。 lazy: true, //是否根据需要懒惰呈现标签,而不是提前制作,意思是在app打开的时候将底部标签栏全部加载,默认false,推荐改成true哦 initialRouteName: 'More', //设置默认的页面组件 backBehavior: 'none', //按 back 键是否跳转到第一个Tab(首页), none 为不跳转 tabBarOptions: { activeTintColor: 'green',//label和icon的前景色 活跃状态下(选中)。 activeBackgroundColor: 'red', //label和icon的背景色 活跃状态下(选中) 。 showLabel: true, //是否显示label,默认开启 labelStyle: {fontSize: 12}, //label的样式 style: {height: 50}, //tabbar的样式 iconStyle: {height: 30} //安卓, } }); export default App;
const MyApp = TabNavigator({ Home: { screen: Home, navigationOptions: { //也可以写在组件内部的static navigationOptions内 tabBarLabel: '首页', tabBarIcon: ({tintColor}) => (<Image source={require('./images/camera.png')} style={{tintColor: tintColor}}/>) } }, Notifications: { screen: Two, navigationOptions: { tabBarLabel: '2页', tabBarIcon: ({tintColor}) => (<Image source={require('./images/add.png')} style={[{tintColor: tintColor}, styles.icon]}/>) } }, Me: { screen: Three, navigationOptions: { tabBarLabel: '3页', tabBarIcon: ({tintColor}) => (<Image source={require('./images/more.png')} style={{tintColor: tintColor}}/>) } } }, { animationEnabled: false, // 切换页面时是否有动画效果 tabBarPosition: 'bottom', // 显示在底端,android 默认是显示在页面顶端的 swipeEnabled: true, // 是否可以左右滑动切换tab backBehavior: 'none', // 按 back 键是否跳转到第一个Tab(首页), none 为不跳转 tabBarOptions: { activeTintColor: '#ff8500', // 文字和图片选中颜色 inactiveTintColor: '#999', // 文字和图片未选中颜色 showIcon: true, // android 默认不显示 icon, 需要设置为 true 才会显示 indicatorStyle: { height: 0 // 如TabBar下面显示有一条线,可以设高度为0后隐藏 }, style: { backgroundColor: '#fff', // TabBar 背景色 // height: 44 }, labelStyle: { fontSize: 10, // 文字大小 }, }, });
3.常用属性介绍
第一个参数RouteConfigs :
RouteConfigs 对象是从路由名称映射到一个路由配置,它告诉导航以呈现该路线什么,参照 StackNavigator第二个参数:TabNavigatorConfig
tabBarComponent
- 要用作标签栏的组件,例如 (这是iOS上的默认设置), (这是Android上的默认设置)TabBarBottom
TabBarTop
tabBarPosition
- 标签栏的位置可以是或'top'
'bottom'
swipeEnabled
- 是否允许在标签之间进行滑动animationEnabled
- 是否在更改标签时进行动画处理lazy
- 是否根据需要懒惰呈现标签,而不是提前制作tabBarOptions
- 配置标签栏,如下所示。
几个选项被传递到底层路由器来修改导航逻辑:
initialRouteName
- 第一次加载时初始标签路由的routeNameorder
- 定义选项卡顺序的routeNames数组paths
- 将routeName映射到路径配置,该配置将覆盖routeConfigs中设置的路径。backBehavior
- 后退按钮是否会使Tab键切换到初始选项卡?如果是的话,设置为,否则。默认为行为。initialRoute
none
initialRoute
tabBarOptions
for (iOS上的默认标签栏)TabBarBottom
activeTintColor
- 活动标签的标签和图标颜色activeBackgroundColor
- 活动选项卡的背景颜色inactiveTintColor
- 不活动标签的标签和图标颜色inactiveBackgroundColor
- 非活动标签的背景颜色showLabel
- 是否显示标签的标签,默认为truestyle
- 标签栏的样式对象labelStyle
- 选项卡标签的样式对象tabStyle
- 标签的样式对象
例:
tabBarOptions: {
activeTintColor: '#e91e63',
labelStyle: {
fontSize: 12,
},
style: {
backgroundColor: 'blue',
},
}
tabBarOptions
for (Android上的默认标签栏)TabBarTop
activeTintColor
- 活动标签的标签和图标颜色inactiveTintColor
- 不活动标签的标签和图标颜色showIcon
- 是否显示标签的图标,默认值为falseshowLabel
- 是否显示标签的标签,默认为trueupperCaseLabel
- 是否使标签大写,默认为truepressColor
- 颜色纹理(Android> = 5.0)pressOpacity
- 按压标签的不透明度(iOS和Android <5.0 only)scrollEnabled
- 是否启用可滚动选项卡tabStyle
- 标签的样式对象indicatorStyle
- 标签指示器的样式对象(选项卡底部的行)labelStyle
- 选项卡标签的样式对象iconStyle
- 标签图标的样式对象style
- 标签栏的样式对象
例:
tabBarOptions: {
labelStyle: {
fontSize: 12,
},
tabStyle: {
width: 100,
},
style: {
backgroundColor: 'blue',
},
}
title
通用标题可以用作备用和headerTitle
tabBarLabel
tabBarVisible
True或false显示或隐藏选项卡栏,如果未设置,则默认为true
tabBarIcon
React Element或者一个给定的函数返回一个React.Element,以在tab栏中显示{ focused: boolean, tintColor: string }
tabBarLabel
标签栏或React元素中显示的标签的标题字符串或者给定的函数返回一个React.Element,以在标签栏中显示。当未定义时,使用场景。要隐藏,请参见上一节。{ focused: boolean, tintColor: string }
title
tabBarOptions.showLabel
/** * Created by 卓原 on 2017/10/31. * zhuoyuan93@gmail.com */ import React from 'react'; import { View, Text, StyleSheet, Button, Image } from 'react-native'; import {DrawerNavigator} from 'react-navigation'; class Home extends React.Component { static navigationOptions = { drawerLabel: 'Notifications标题', drawerIcon: ({tintColor}) => ( <Image source={require('../../img/ic_launcher.png')} style={[styles.icon, {tintColor: tintColor}]} /> ), }; render() { const {navigate} = this.props.navigation; return ( <View style={styles.container}> <Text onPress={() => navigate('Home2', {name: '从Home到HOme2'}) }>跳到新页面</Text> <Text onPress={() => navigate('DrawerOpen') }>打开抽屉</Text> </View> ) } } class MyNotificationsScreen extends React.Component { static navigationOptions = { drawerLabel: 'Notifications标题', drawerIcon: ({tintColor}) => ( <Image source={require('../../img/ic_launcher.png')} style={[styles.icon, {tintColor: tintColor}]} /> ), }; render() { return ( <Button onPress={() => this.props.navigation.goBack()} title="Go back home" /> ); } } const Drawer = DrawerNavigator({ Home: { screen: Home, navigationOptions:{ drawerLabel:'帅气Home', headerTitle:'home title', drawerIcon: ({tintColor}) => ( <Image source={require('../../img/ic_launcher.png')} style={[styles.icon, {tintColor: tintColor}]} /> ), } }, Notifications: { screen: MyNotificationsScreen, }, Notifications2: { screen: MyNotificationsScreen, }, }, { drawerWidth: 200, //抽屉的宽度 drawerPosition: 'left' , //选项是left和right.默认是left // contentComponent:(navigation)=><Text>asa</Text>, contentOptions: { activeTintColor: '#e91e63', itemsContainerStyle: { marginVertical: 0, }, iconContainerStyle: { opacity: 1 }, } }); const styles = StyleSheet.create({ container: { marginTop: 22 }, icon: { width: 24, height: 24, }, }); export default Drawer;
用于轻松设置带抽屉导航的屏幕。有关实例,请参阅我们的展会演示。
class MyHomeScreen extends React.Component {
static navigationOptions = {
drawerLabel: 'Home',
drawerIcon: ({ tintColor }) => (
<Image
source={require('./chats-icon.png')}
style={[styles.icon, {tintColor: tintColor}]}
/>
),
};
render() {
return (
<Button
onPress={() => this.props.navigation.navigate('Notifications')}
title="Go to notifications"
/>
);
}
}
class MyNotificationsScreen extends React.Component {
static navigationOptions = {
drawerLabel: 'Notifications',
drawerIcon: ({ tintColor }) => (
<Image
source={require('./notif-icon.png')}
style={[styles.icon, {tintColor: tintColor}]}
/>
),
};
render() {
return (
<Button
onPress={() => this.props.navigation.goBack()}
title="Go back home"
/>
);
}
}
const styles = StyleSheet.create({
icon: {
width: 24,
height: 24,
},
});
const MyApp = DrawerNavigator({
Home: {
screen: MyHomeScreen,
},
Notifications: {
screen: MyNotificationsScreen,
},
});
打开和关闭抽屉,导航到并分别。'DrawerOpen'
'DrawerClose'
this.props.navigation.navigate('DrawerOpen'); // open drawer
this.props.navigation.navigate('DrawerClose'); // close drawer
API定义
DrawerNavigator(RouteConfigs, DrawerNavigatorConfig)
RouteConfigs
路由CONFIGS对象是从路由名称映射到一个路由配置,它告诉导航以呈现该路线什么,参见例如由。StackNavigator
DrawerNavigatorConfig
drawerWidth
- 抽屉的宽度drawerPosition
- 选项是或。默认是位置。left
right
left
contentComponent
- 用于呈现抽屉内容的组件,例如导航项。接收抽屉的支柱。默认为。有关详细信息,请参阅下文。navigation
DrawerItems
contentOptions
- 配置抽屉内容,见下文。
示例:
默认是不可滚动。要实现可滚动,您必须使用该属性定制容器,如下面的示例所示。DrawerView
View
contentComponent
{
drawerWidth: 200,
drawerPosition: 'right',
contentComponent: props => <ScrollView><DrawerItems {...props} /></ScrollView>
}
几个选项被传递到底层路由器来修改导航逻辑:
initialRouteName
- 初始路由的routeName。order
- 定义抽屉物品顺序的routeNames数组。paths
- 将routeName映射到路径配置,该配置将覆盖routeConfigs中设置的路径。backBehavior
- 后退按钮是否会切换到初始路线?如果是的话,设置为,否则。默认为行为。initialRoute
none
initialRoute
提供自定义contentComponent
您可以轻松地覆盖所使用的默认组件:react-navigation
import { DrawerItems } from 'react-navigation';
const CustomDrawerContentComponent = (props) => (
<View style={style.container}>
<DrawerItems {...props} />
</View>
);
const styles = StyleSheet.create({
container: {
flex: 1,
},
});
contentOptions
为DrawerItems
items
- 路由数组,可以修改或覆盖activeItemKey
- 标识活动路线的钥匙activeTintColor
- 活动标签的标签和图标颜色activeBackgroundColor
- 活动标签的背景颜色inactiveTintColor
- 无效标签的标签和图标颜色inactiveBackgroundColor
- 非活动标签的背景颜色onItemPress(route)
- 按下项目时调用的功能style
- 内容部分的样式对象labelStyle
- 当您的标签是字符串时,样式对象将覆盖内容部分中的样式Text
示例:
contentOptions: {
activeTintColor: '#e91e63',
style: {
marginVertical: 0,
}
}
屏幕导航选项
title
通用标题可以用作备用和headerTitle
drawerLabel
drawerLabel
String,React元素或给定的函数返回一个React.Element,显示在抽屉侧边栏中。当不确定,现场使用{ focused: boolean, tintColor: string }
title
drawerIcon
React Element或一个函数,返回一个React.Element,显示在抽屉侧边栏中{ focused: boolean, tintColor: string }
导航道具
创建的导航器组件需要以下道具:DrawerNavigator(...)
screenProps
- 向儿童屏幕传递额外的选项,例如:
const DrawerNav = DrawerNavigator({
// config
});
<DrawerNav
screenProps={/* this prop will get passed to the screen components and nav options as props.screenProps */}
/>
嵌套#DrawerNavigation
请记住,如果您嵌套DrawerNavigation,抽屉将显示在父导航下方。
withNavigation
withNavigation是一个更高阶的组件,它将导航道具传递给一个包装组件。当您无法直接将导航道具传递到组件时,或者在深度嵌套子节点的情况下不希望传递导航道具时,它非常有用。
import React from 'react';
import { Button } from 'react-native';
import { withNavigation } from 'react-navigation';
class MyBackButton extends React.Component {
render() {
return <Button title="Back" onPress={() => { this.props.navigation.goBack() }} />;
}
}
// withNavigation returns a component that wraps MyBackButton and passes in the
// navigation prop
export default withNavigation(MyBackButton);