React Native 导航器详解:React Navigation 入门指南
React Navigation 是 React Native 中一款强大的导航组件,被视为 Navigator 的增强版。它支持底部导航(类似 iOS 中的 UITabBarController)以及侧拉抽屉效果(类似 Android 中的 DrawerLayout),为移动应用提供灵活的导航结构。
导航器概述
导航器可以看作普通的 React 组件,用于定义应用的导航结构。它还能渲染通用元素,如标题栏、底部标签栏和顶部选项卡栏。在 React Navigation 中,主要包含以下七种导航器类型:
- createStackNavigator:类似标准的 Navigator,提供屏幕上方导航栏。
- createBottomTabNavigator:替代已弃用的 createTabNavigator,实现屏幕底部导航栏。
- createMaterialTopTabNavigator:屏幕顶部的材料设计主题标题栏。
- createDrawerNavigator:侧边滑出的抽屉效果导航。
- createSwitchNavigator:一次只显示一个页面,常用于身份验证流程。
- 此外,还有 createTabNavigator(已弃用)等。
在学习这些导航器之前,需要先理解两个核心概念:Screen navigation prop(屏幕导航属性)和 Screen navigationOptions(屏幕导航选项)。通过 navigation prop,可以完成屏幕之间的调度操作;而 navigationOptions 用于定制导航器显示屏幕的方式,例如设置头部标题或选项卡标签。
Screen Navigation Prop 详解
当导航器中的屏幕被打开时,它会接收一个 navigation prop,这是导航环节的关键。navigation prop 提供以下主要功能:
- navigate:跳转到其他页面。
- state:获取屏幕当前状态。
- setParams:改变路由的参数。
- goBack:关闭当前屏幕。
- dispatch:向路由发送一个 action。
- addListener:订阅导航生命周期的更新。
- isFocused:标志屏幕是否获取焦点。
- getParam:获取特定参数。
- dangerouslyGetParent:返回父导航器。
使用 navigation.navigate 进行界面跳转的基本语法为 navigation.navigate(routeName, params, action) 或 navigation.navigate({routeName, params, action, key})。其中,routeName 是要跳转界面的路由名,params 是传递给下一个界面的参数,action 用于子导航操作,key 是可选的标识符。
常用导航器解析
createStackNavigator
createStackNavigator 提供应用屏幕之间的切换能力,以栈的形式管理导航,新切换到的屏幕会置于栈顶。默认转场效果在 Android 上为底部淡入,在 iOS 上为右侧划入,但可通过配置自定义。
API 格式:createStackNavigator(RouteConfigs, StackNavigatorConfig)。RouteConfigs 是必选的路由配置对象,定义路由名称到路由配置的映射;StackNavigatorConfig 为可选的导航器配置。
基本使用步骤:
- 安装依赖:
yarn add react-navigation - 添加手势处理:
yarn add react-native-gesture-handler - 链接原生模块:
react-native link react-native-gesture-handler
createMaterialTopTabNavigator 与 createBottomTabNavigator
createMaterialTopTabNavigator 用于屏幕顶部标签栏,而 createBottomTabNavigator 用于底部标签栏。它们的 API 类似:createNavigator(RouteConfigs, TabNavigatorConfig)。
TabNavigatorConfig 特有配置包括:
- tabBarComponent:指定 TabBar 组件。
- tabBarPosition:标签栏位置,支持 'top' 或 'bottom'。
- swipeEnabled:是否允许左右滑动切换标签。
- lazy:设置为 true 时可实现标签页懒加载。
- animationEnabled:切换页面时是否启用动画效果。
- tabBarOptions:配置标签栏样式,如 activeTintColor(选中颜色)、inactiveTintColor(未选中颜色)、showIcon(是否显示图标)、style(整体样式)等。
createDrawerNavigator
createDrawerNavigator 实现侧边抽屉导航。其配置参数 DrawerNavigatorConfig 包括:
- drawerWidth:设置侧边菜单宽度。
- drawerPosition:菜单位置,支持 'left' 或 'right'。
- contentComponent:自定义侧边栏内容组件,默认使用 DrawerItems。
- contentOptions:配置侧边栏项属性,如 activeTintColor、inactiveBackgroundColor 等。
- drawerBackgroundColor:侧边菜单背景色。
自定义侧边栏时,可通过重写 contentComponent 来渲染自定义组件,例如结合 ScrollView 和 SafeAreaView 适配全面屏。
createSwitchNavigator
createSwitchNavigator 用于一次仅显示一个页面的场景,如登录流程。默认不处理返回操作,并在切换时重置路由状态。
API:createSwitchNavigator(RouteConfigs, SwitchNavigatorConfig)。SwitchNavigatorConfig 支持 initialRouteName(初始路由)、resetOnBlur(离开屏幕时是否重置状态)等配置。
代码示例与整合
以下是一个综合示例,展示如何整合多种导航器:
import React, {Component} from 'react';
import {Platform, Button, ScrollView, SafeAreaView, View} from 'react-native';
import {createStackNavigator, createMaterialTopTabNavigator, createBottomTabNavigator, createDrawerNavigator, DrawerItems, createSwitchNavigator} from 'react-navigation';
import Ionicons from 'react-native-vector-icons/Ionicons';
import MaterialIcons from 'react-native-vector-icons/MaterialIcons';
import HomePage from '../pages/HomePage';
import Page1 from '../pages/Page1';
import Page2 from '../pages/Page2';
import Page3 from '../pages/Page3';
import Page4 from '../pages/Page4';
import Page5 from '../pages/Page5';
import Login from '../pages/Login';
const AppStack = createStackNavigator({
Home: { screen: HomePage },
Page1: { screen: Page1 }
});
const AuthStack = createStackNavigator({
Login: { screen: Login }
});
export const AppSwitchNavigator = createSwitchNavigator({
Auth: AuthStack,
App: AppStack
}, {
initialRouteName: 'Auth'
});
const TopNavigator = createMaterialTopTabNavigator({
Page1: { screen: Page1, navigationOptions: { tabBarLabel: 'Android' } },
Page2: { screen: Page2, navigationOptions: { tabBarLabel: 'iOS' } },
Page3: { screen: Page3, navigationOptions: { tabBarLabel: 'React' } },
Page4: { screen: Page4, navigationOptions: { tabBarLabel: 'React Native' } },
Page5: { screen: Page5, navigationOptions: { tabBarLabel: 'My Pleasure' } }
}, {
tabBarOptions: {
tabStyle: { minWidth: 50 },
upperCaseLabel: false,
scrollEnabled: true,
style: { backgroundColor: '#678' },
indicatorStyle: { height: 2, backgroundColor: 'pink' },
labelStyle: { fontSize: 13, marginTop: 6, marginBottom: 6 }
}
});
const BottomNavigator = createBottomTabNavigator({
Page1: {
screen: Page1,
navigationOptions: {
tabBarLabel: '最热',
tabBarIcon: ({tintColor}) => <Ionicons name={'ios-home'} size={26} style={{color: tintColor}} />
}
},
Page2: {
screen: Page2,
navigationOptions: {
tabBarLabel: '趋势',
tabBarIcon: ({tintColor}) => <Ionicons name={'ios-people'} size={26} style={{color: tintColor}} />
}
},
Page3: {
screen: Page3,
navigationOptions: {
tabBarLabel: '收藏',
tabBarIcon: ({tintColor}) => <Ionicons name={'ios-chatboxes'} size={26} style={{color: tintColor}} />
}
},
Page4: {
screen: Page4,
navigationOptions: {
tabBarLabel: '我的',
tabBarIcon: ({tintColor}) => <Ionicons name={'ios-aperture'} size={26} style={{color: tintColor}} />
}
}
}, {
tabBarOptions: { activeTintColor: 'red' }
});
const DrawerNavigator = createDrawerNavigator({
Page4: {
screen: Page4,
navigationOptions: {
drawerLabel: 'Page4',
drawerIcon: ({tintColor}) => <MaterialIcons name={'drafts'} size={24} style={{color: tintColor}} />
}
},
Page5: {
screen: Page5,
navigationOptions: {
drawerLabel: 'Page5',
drawerIcon: ({tintColor}) => <MaterialIcons name={'move-to-inbox'} size={24} style={{color: tintColor}} />
}
}
}, {
initialRouteName: 'Page4',
contentOptions: { activeTintColor: '#e91e63' },
contentComponent: (props) => (
<ScrollView style={{backgroundColor: '#789', flex: 1}}>
<SafeAreaView forceInset={{top: 'always', horizontal: 'never'}}>
<DrawerItems {...props} />
</SafeAreaView>
</ScrollView>
),
drawerLockMode: 'unlocked'
});
export const AppStackNavigator = createStackNavigator({
HomePage: { screen: HomePage },
Page1: {
screen: Page1,
navigationOptions: ({navigation}) => ({ title: `${navigation.state.params.name}页面名` })
},
Page2: { screen: Page2, navigationOptions: { title: 'This is Page2' } },
Page3: {
screen: Page3,
navigationOptions: (props) => {
const {navigation} = props;
const {state, setParams} = navigation;
const {params} = state;
return {
title: params.title ? params.title : 'This is Page3',
headerRight: (
<Button
title={params.mode === 'edit' ? '保存' : '编辑'}
onPress={() => setParams({mode: params.mode === 'edit' ? '' : 'edit'})}
/>
)
};
}
},
Page4: { screen: Page4, navigationOptions: { title: 'This is Page4' } },
Bottom: { screen: BottomNavigator, navigationOptions: { title: 'BottomNavigator' } },
Top: { screen: TopNavigator, navigationOptions: { title: 'TopNavigator' } },
DrawerNav: { screen: DrawerNavigator, navigationOptions: { title: 'DrawerNav' } }
});
此示例展示了如何结合多种导航器构建复杂应用结构,具体代码可参考相关资源进行扩展。通过合理配置导航器,可以高效管理 React Native 应用的页面切换和用户流程。