除了上面我们所介绍的 Stack 类型导航以外,React Navigation 中提供了常用的其他类型的导航。本小节我们就一起来看一下这些常用导航类型,主要包括:
- Tab navigation
- Drawer navigation
- Material Top Tabs Navigator
Tab navigation#
移动应用程序中最常见的导航样式可能是基于选项卡的导航。这可以是屏幕底部的选项卡,也可以是标题下方顶部的选项卡(甚至可以代替标题)。
首先安装 @react-navigation/bottom-tabs:
npm install @react-navigation/bottom-tabs下面是一个 Tab navigation 最基本的示例:
import * as React from 'react'import { Text, View } from 'react-native'import { NavigationContainer } from '@react-navigation/native'import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'
function HomeScreen() { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>Home!</Text> </View> )}
function SettingsScreen() { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>Settings!</Text> </View> )}
const Tab = createBottomTabNavigator()
function MyTabs() { return ( <Tab.Navigator> <Tab.Screen name="Home" component={HomeScreen} /> <Tab.Screen name="Settings" component={SettingsScreen} /> </Tab.Navigator> )}
export default function App() { return ( <NavigationContainer> <MyTabs /> </NavigationContainer> )}我们同样可以自定义外观,这类似于之前所介绍的 Stack 路由的方式,在初始化选项卡导航器时会设置一些属性,而其他属性可以在选项中按屏幕自定义。
// You can import Ionicons from @expo/vector-icons if you use Expo or// react-native-vector-icons/Ionicons otherwise.import * as React from 'react'import { Text, View } from 'react-native'import { Ionicons } from '@expo/vector-icons'import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'import { NavigationContainer } from '@react-navigation/native'
function HomeScreen() { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>Home!</Text> </View> )}
function MailScreen() { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>Settings!</Text> </View> )}
const Tab = createBottomTabNavigator()
export default function App() { return ( <NavigationContainer> <Tab.Navigator screenOptions={({ route }) => ({ tabBarIcon: ({ focused, color, size }) => { let iconName
if (route.name === 'Home') { iconName = focused ? 'ios-information-circle' : 'ios-information-circle-outline' } else if (route.name === 'Mail') { iconName = focused ? 'ios-mail' : 'ios-mail-unread' }
// You can return any component that you like here! return <Ionicons name={iconName} size={size} color={color} /> }, tabBarActiveTintColor: 'tomato', tabBarInactiveTintColor: 'gray', })} > <Tab.Screen name="Home" component={HomeScreen} /> <Tab.Screen name="Mail" component={MailScreen} /> </Tab.Navigator> </NavigationContainer> )}在上面的示例中,我们用到了 tabBarIcon 属性,该属性是底部选项卡导航器中支持的选项,需要将它放在 Tab.Navigator 的 screenOptions 属性中是为了方便集中图标配置。tabBarIcon 是一个函数,它被赋予了焦点状态、颜色和大小参数。另外,tabBarActiveTintColor 和 tabBarInactiveTintColor 表示活动以及非活动的颜色值。
有时我们想给一些图标添加徽章。可以使用 tabBarBadge 选项来执行此操作:
<Tab.Screen name="Mail" component={MailScreen} options={{ tabBarBadge: 3 }} />当我们处于某一屏中,想要通过屏幕中的按钮进行 Tab 跳转可以使用 navigation.navigate
import * as React from 'react'import { Button, Text, View } from 'react-native'import { NavigationContainer } from '@react-navigation/native'import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'
function HomeScreen({ navigation }) { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>Home!</Text> <Button title="Go to Settings" onPress={() => navigation.navigate('Settings')} /> </View> )}
function SettingsScreen({ navigation }) { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>Settings!</Text> <Button title="Go to Home" onPress={() => navigation.navigate('Home')} /> </View> )}
const Tab = createBottomTabNavigator()
export default function App() { return ( <NavigationContainer> <Tab.Navigator> <Tab.Screen name="Home" component={HomeScreen} /> <Tab.Screen name="Settings" component={SettingsScreen} /> </Tab.Navigator> </NavigationContainer> )}很多时候,我们的某一屏并不是只属于某一个 Tab 栏,而是有多个 Tab 栏都可以跳转到这一屏,下面是一个这种情况的示例:
import * as React from 'react'import { Button, Text, View } from 'react-native'import { NavigationContainer } from '@react-navigation/native'import { createNativeStackNavigator } from '@react-navigation/native-stack'import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'
function DetailsScreen() { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>Details!</Text> </View> )}
function HomeScreen({ navigation }) { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>Home screen</Text> <Button title="Go to Details" onPress={() => navigation.navigate('Details')} /> </View> )}
function SettingsScreen({ navigation }) { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>Settings screen</Text> <Button title="Go to Details" onPress={() => navigation.navigate('Details')} /> </View> )}
const HomeStack = createNativeStackNavigator()
function HomeStackScreen() { return ( <HomeStack.Navigator> <HomeStack.Screen name="Home" component={HomeScreen} /> <HomeStack.Screen name="Details" component={DetailsScreen} /> </HomeStack.Navigator> )}
const SettingsStack = createNativeStackNavigator()
function SettingsStackScreen() { return ( <SettingsStack.Navigator> <SettingsStack.Screen name="Settings" component={SettingsScreen} /> <SettingsStack.Screen name="Details" component={DetailsScreen} /> </SettingsStack.Navigator> )}
const Tab = createBottomTabNavigator()
export default function App() { return ( <NavigationContainer> <Tab.Navigator screenOptions={{ headerShown: false }}> <Tab.Screen name="Home" component={HomeStackScreen} /> <Tab.Screen name="Settings" component={SettingsStackScreen} /> </Tab.Navigator> </NavigationContainer> )}更多关于 Tab navigation 标签页导航的 API,可以参阅 https://reactnavigation.org/docs/bottom-tab-navigator#api-definition
Drawer navigation#
Drawer navigation 翻译成中文叫做抽屉导航,其实就是导航中常见的使用左侧(有时是右侧)的抽屉在屏幕之间导航。
首先第一步还是需要安装该类型的导航:
npm i @react-navigation/drawer除了安装 @react-navigation/drawer 依赖库以外,这种类型的导航还需要额外安装 react-native-gesture-handler 以及 react-native-reanimated 依赖库,然后将下面的:
import 'react-native-gesture-handler'放在入口文件的最上面,并且在 babel.config.js 中添加 plugins,具体操作如下图:
具体安装步骤请参阅:https://reactnavigation.org/docs/drawer-navigator#installation
下面是一个关于抽屉导航的简单示例:
import 'react-native-gesture-handler'import * as React from 'react'import { Button, View } from 'react-native'import { createDrawerNavigator } from '@react-navigation/drawer'import { NavigationContainer } from '@react-navigation/native'
function HomeScreen({ navigation }) { return ( <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}> <Button onPress={() => navigation.navigate('Notifications')} title="Go to notifications" /> </View> )}
function NotificationsScreen({ navigation }) { return ( <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}> <Button onPress={() => navigation.goBack()} title="Go back home" /> </View> )}
const Drawer = createDrawerNavigator()
export default function App() { return ( <NavigationContainer> <Drawer.Navigator useLegacyImplementation initialRouteName="Home"> <Drawer.Screen name="Home" component={HomeScreen} /> <Drawer.Screen name="Notifications" component={NotificationsScreen} /> </Drawer.Navigator> </NavigationContainer> )}注:添加 Babel 插件后,重新启动开发服务器并清除捆绑程序缓存:expo start —clear。
可以通过 open 和 close 方法来打开或者关闭抽屉,通过 toggleDrawer 来切换抽屉。
示例如下:
import * as React from 'react'import { View, Text, Button } from 'react-native'import { NavigationContainer } from '@react-navigation/native'import { createDrawerNavigator, DrawerContentScrollView, DrawerItemList, DrawerItem,} from '@react-navigation/drawer'
function Feed({ navigation }) { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>Feed Screen</Text> <Button title="Open drawer" onPress={() => navigation.openDrawer()} /> <Button title="Toggle drawer" onPress={() => navigation.toggleDrawer()} /> </View> )}
function Notifications() { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>Notifications Screen</Text> </View> )}
function CustomDrawerContent(props) { return ( <DrawerContentScrollView {...props}> <DrawerItemList {...props} /> <DrawerItem label="Close drawer" onPress={() => props.navigation.closeDrawer()} /> <DrawerItem label="Toggle drawer" onPress={() => props.navigation.toggleDrawer()} /> </DrawerContentScrollView> )}
const Drawer = createDrawerNavigator()
function MyDrawer() { return ( <Drawer.Navigator useLegacyImplementation drawerContent={(props) => <CustomDrawerContent {...props} />} > <Drawer.Screen name="Feed" component={Feed} /> <Drawer.Screen name="Notifications" component={Notifications} /> </Drawer.Navigator> )}
export default function App() { return ( <NavigationContainer> <MyDrawer /> </NavigationContainer> )}更多关于 Drawer navigation 抽屉导航的 API,可以参阅 https://reactnavigation.org/docs/drawer-navigator#api-definition
Material Top Tabs Navigator#
Material Top Tabs Navigator 翻译成中文叫做“顶部滑动选项卡导航”。要使用这种导航,首先还是需要先安装依赖,命令如下:
npm install @react-navigation/material-top-tabs react-native-tab-view除了上面的依赖以外,还需要安装 react-native-pager-view。因为我们是使用 expo 搭建的项目,因此安装指令如下:
expo install react-native-pager-view到这里,依赖安装就完毕了,下面是一个这种导航的简单示例:
import * as React from 'react'import { Text, View } from 'react-native'import { NavigationContainer } from '@react-navigation/native'import { createMaterialTopTabNavigator } from '@react-navigation/material-top-tabs'
function HomeScreen() { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>Home!</Text> </View> )}
function SettingsScreen() { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>Settings!</Text> </View> )}
const Tab = createMaterialTopTabNavigator()
export default function App() { return ( <NavigationContainer> <Tab.Navigator> <Tab.Screen name="Home" component={HomeScreen} /> <Tab.Screen name="Settings" component={SettingsScreen} /> </Tab.Navigator> </NavigationContainer> )}更多关于 Material Top Tabs Navigator 顶部滑动选项卡导航的 API,可以参阅 https://reactnavigation.org/docs/material-top-tab-navigator#api-definition