react-navigation是一个很好用的导航组件,官方文档也很详细:https://reactnavigation.org/docs/intro/ 虽然用的很爽,但是在使用过程中还是遇到了一些问题,最大的问题是如何进行项目中的导航嵌套。
首先介绍一下react-navigation中导航的三种形式:
1.StackNavigator 页面堆栈导航
2.TabNavigator 底部(或顶部)标签导航
3.DrawerNavigator 侧边栏滑动导航
关于这三种导航具体是什么样子的,可以自己试试或者看官方网站中他们在Expo上有个演示的app,很详细。
在项目中遇到的问题是如何组织嵌套这三种导航,需要实现的导航效果是有一个左边滑动导航,一个底部的4个标签的导航,然后在页面中点击按钮会转到新的堆栈导航,效果如图
但是构建项目的时候如何组织嵌套这三种代码,经过了很多次不同的尝试,参考官方github的issue:https://github.com/react-community/react-navigation/issues/1849
有人推荐可以这样嵌套
StackNavigator
- TabNavigator
- DrawerNavigator
( 官方文档中关于DrawerNavigator最后有这样一句话:
Please bear in mind that if you nest the DrawerNavigation, the drawer will show below the parent navigation. 如果按上面那样实现嵌套的话,侧边栏的滑动导航高度不会占全屏,StackNavigator的顶栏会占去一部分高度,drawer是在stack下面的)
然后还举了个Android Twitter的例子:
StackNavigator
- Login Screen
- Home Screen
+ TabNavigator
- Feed
- Search
- Notifications
- Messages
- DrawerNavigator
(custom made the content & drawer list to call navigation.navigate)
- Profile
- Highlights
- Moments
- Lists
- Connect
...etc
```
经过多次尝试,我的嵌套导航是这样的
DrawerNavigator
- StackNavigator
- TabNavigator
即Drawer是根导航,stack嵌套在其下,然后tab又嵌套在stack下。
这样做有一个小小的奇怪的地方,就是Drawer中会显示三个导航,如图中有“我的”“登录”,原本在“我的”上面还有一个标签,用来回到主页,但是看上去很奇怪就没有设置标签文字,但是应该是有办法不显示的,我一开始想的是直接改动node_modules中引用的源代码判断第一条不显示。。。后来想想不对啊,,,npm install的时候岂不是,,,然后没有想到解决办法只是把标签内的文字设成空的。
为方便参考,下面是我的导航组件的源代码
import React, { Component } from 'react';
import {
StyleSheet,
Text,
Button,
ScrollView,
View
} from 'react-native';
import { StackNavigator, TabNavigator, DrawerNavigator } from 'react-navigation';
import { DrawerItems } from 'react-navigation';
// 实现自定义IconFont更好用,取消引入Ionicons
// import Ionicons from 'react-native-vector-icons/Ionicons';
import { IconFont } from './IconFont';
// 首页
import { HomeScreen } from '../views/HomeScreen';
// 打卡页面
import { CardScreen } from '../views/CardScreen';
// 清单页面
import { ListScreen } from '../views/ListScreen';
// 记账页面
import { AccountScreen } from '../views/AccountScreen';
// 我的页面
import { MyScreen } from '../views/MyScreen';
// 登录页面
import { LoginScreen } from '../views/LoginScreen';
// 添加卡片
import { AddCard } from '../views/Card/AddCard';
// 添加清单
import { AddList } from '../views/List/AddList';
// 清单列表
import { ListContent } from '../views/List/ListContent';
// 清单详情
import { ListDetail } from '../views/List/ListDetail';
/*
* stackNavigator
* 四个主页面
*/
const stackOption = {
navigationOptions: {
headerTintColor: '#fff',
headerStyle: {
backgroundColor: '#6495ED',//矢车菊蓝
}
}
}
// 我的导航
const MyStack = StackNavigator({
MyScreen: {
screen: MyScreen,
navigationOptions: {
title: '我的',
tabBarLabel: '我的',
tabBarIcon: ({ tintColor, focused }) => (
<Ionicons
name={'md-create'}
size={28}
style={{ color: tintColor }}
/>
),
},
},
},stackOption);
/*
* tabNavigator
*
*/
const AppTabNav = TabNavigator({
Home: {
screen: HomeScreen,
navigationOptions: {
title: '梦想助手',
tabBarLabel: '首页',
tabBarIcon: ({ tintColor, focused }) => (
<IconFont
font=""
style={{ color: tintColor, fontSize: 26 }}
/>
),
},
},
Card: {
screen: CardScreen,
navigationOptions: ({ navigation }) => ({
title: '梦想打卡',
tabBarLabel: '打卡',
tabBarIcon: ({ tintColor, focused }) => (
<IconFont
font=""
style={{ color: tintColor, fontSize: 26 }}
/>
),
headerRight: <IconFont
font=""
style={{color: '#fff', marginRight: 15, fontSize: 30}}
onPress={() => navigation.navigate('AddCard') }
/>,
}),
},
List: {
screen: ListScreen,
navigationOptions: ({ navigation }) => ({
title: '梦想清单',
tabBarLabel: '清单',
tabBarIcon: ({ tintColor, focused }) => (
<IconFont
font=""
style={{ color: tintColor, fontSize: 26 }}
/>
),
headerRight: <IconFont
font=""
style={{color: '#fff', marginRight: 15, fontSize: 30}}
onPress={() => navigation.navigate('AddList') }
/>,
}),
},
Account: {
screen: AccountScreen,
navigationOptions: {
title: '记账',
tabBarLabel: '记账',
tabBarIcon: ({ tintColor, focused }) => (
<IconFont
font=""
style={{ color: tintColor, fontSize: 26 }}
/>
),
},
}
}, {
initialRouteName: 'Home',
tabBarPosition: 'bottom',
tabBarOptions: {
showIcon: true,
showLabel: false,
activeTintColor: '#6495ED',
inactiveTintColor: '#666',
indicatorStyle: {
backgroundColor: '#fff',
},
style: {
backgroundColor: '#fff',
borderTopWidth: 1,
borderTopColor: '#f0f0f0',
}
}
});
const AppStack = StackNavigator({
Home: {
screen: AppTabNav,
},
AddCard: {
screen: AddCard,
navigationOptions: {
title: '添加卡片'
}
},
AddList: {
screen: AddList,
navigationOptions: {
title: '添加清单'
}
},
ListContent: {
screen: ListContent,
navigationOptions: {
title: '列表标题'
}
},
ListDetail: {
screen: ListDetail,
navigationOptions: {
title: '列表标题',
headerRight: <IconFont
font=""
style={{color: '#fff', marginRight: 15, fontSize: 28}}
onPress={() => alert("ok") }
/>,
}
},
}, stackOption);
/*
* drawerNavigator
*
*/
// 自定义侧边导航栏
const DrawerContent = (props) => {
return(
<View style={styles.container}>
<View style={styles.header}>
<Text style={styles.welcome}>欢迎</Text>
</View>
<DrawerItems {...props} />
</View>
)
};
export const AppNav = DrawerNavigator({
App: {
screen: AppStack,
navigationOptions: {
title: '',
tabBarLabel: '',
},
},
MyScreen: {
screen: MyStack,
},
LoginScreen: {
screen: LoginScreen
},
},{
contentComponent: props => <ScrollView><DrawerContent {...props} /></ScrollView>
});
const styles = StyleSheet.create({
container: {
flex: 1,
},
header: {
height: 200,
width: '100%'
},
welcome: {
fontSize: 20,
height: 80,
textAlign: 'center',
textAlignVertical: 'center'
},
});