在上一节中,我们使用了系统提供的导航组件进行页面跳转,但其实用性有限。本文将详细介绍一个功能强大的第三方导航库:react-navigation。首先,我们回顾一下React Native中常见的导航控件。
导航控件
常见的导航主要分为三种:
- StackNavigator:类似于普通的导航器,在屏幕上方显示导航栏,用于管理页面堆栈。
- TabNavigator:相当于iOS中的TabBarController,在屏幕底部显示标签栏,用于切换不同模块。
- DrawerNavigator:实现抽屉效果,可以从屏幕侧边滑出菜单。
Navigation 使用
在使用navigation的每个界面,navigation都提供了一系列属性和方法。常见的有:
- navigate:用于跳转到另一个页面。主要参数包括:
routeName:目标路由名称,需在app router中注册。params:传递给目标路由的参数。action:(高级)如果目标界面是navigator,可以运行此sub-action。
- state:通过
this.props.navigation.state访问当前路由状态,包含routeName、key和params等。 - setParams:允许界面动态更改路由中的参数,常用于更新header内容。
- goBack:返回上一级页面。
- dispatch:向任何navigation传递其他action。
例如,在HomeScreen组件中使用navigate进行跳转:
class HomeScreen extends React.Component {
render() {
const {navigate} = this.props.navigation;
return (
<View>
<Text>This is the home screen of the app</Text>
<Button
onPress={() => navigate('Profile', {name: 'Brent'})}
title="点击我跳转"
/>
</View>
)
}
}
Navigate使用示例
通过NavigationActions.navigate创建导航action并dispatch:
import { NavigationActions } from 'react-navigation'
const navigationAction = NavigationActions.navigate({
routeName: 'Profile',
params: {},
action: NavigationActions.navigate({ routeName: 'SubProfileRoute'})
})
this.props.navigation.dispatch(navigationAction)
Reset方法使用
Reset方法会清除所有导航状态,并用新的路由替代:
import { NavigationActions } from 'react-navigation'
const resetAction = NavigationActions.reset({
index: 0,
actions: [
NavigationActions.navigate({ routeName: 'Profile'})
]
})
this.props.navigation.dispatch(resetAction)
SetParams方法使用
为指定路由更新参数,该路由必须已存在:
import { NavigationActions } from 'react-navigation'
const setParamsAction = NavigationActions.setParams({
params: {},
key: 'screen-123',
})
this.props.navigation.dispatch(setParamsAction)
StackNavigator使用
StackNavigator使用简单,下面是一个常见示例:
class MyHomeScreen extends React.Component {
static navigationOptions = {
title: 'Home',
}
render() {
return (
<Button
onPress={() => this.props.navigation.navigate('Profile', {name: 'Lucy'})}
title="Go to Lucy's profile"
/>
);
}
}
const ModalStack = StackNavigator({
Home: {
screen: MyHomeScreen,
},
Profile: {
path: 'people/:name',
screen: MyProfileScreen,
},
});
StackNavigatorConfig配置
StackNavigator的配置选项包括路由选项和视觉选项:
- 路由选项:
initialRouteName:设置默认界面,需与route configs中的key匹配。initialRouteParams:初始路由的参数。navigationOptions:屏幕导航的默认选项。paths:路由路径设置的映射。
- 视觉选项:
mode:定义渲染和转换模式,可选card(标准iOS/Android切换)或modal(仅iOS,模态视图)。headerMode:指定header渲染方式,可选float(共用header,有渐变效果)、screen(各自header,无渐变)或none(无header)。cardStyle:继承或重载stack中card的样式。onTransitionStart和onTransitionEnd:换场动画开始和结束时的回调函数。
Navigation Options配置
可以在组件中定义静态的navigationOptions来定制导航栏:
class ProfileScreen extends React.Component {
static navigationOptions = {
title: ({ state }) => `${state.params.name}'s Profile!`,
header: ({ state, setParams }) => ({
right: (
<Button
title={state.params.editing ? 'Done' : 'Edit'}
onPress={() => setParams({editing: state.params.editing ? false : true})}
/>
),
}),
};
// ...
}
常用配置参数:
visible:布尔值,控制header是否可见。title:标题,可以是字符串或React节点。backTitle:iOS平台返回按钮的标题,默认为title值。right和left:在header右侧或左侧显示的React节点,如按钮。style:header的样式。titleStyle:header标题的样式。tintColor:header的前景色。cardStack:配置card stack。
react-navigation使用详解
安装与基本使用
首先,在项目目录下安装react-navigation库:
npm install --save react-navigation
然后,使用StackNavigator管理页面堆栈。以下是一个简单的入口页面示例:
import React from 'react';
import { AppRegistry, Text } from 'react-native';
import { StackNavigator } from 'react-navigation';
class HomeScreen extends React.Component {
static navigationOptions = {
title: 'Welcome',
};
render() {
return <Text>Hello, Navigation!</Text>;
}
}
const SimpleApp = StackNavigator({
Home: { screen: HomeScreen },
});
AppRegistry.registerComponent('SimpleApp', () => SimpleApp);
添加一个新页面ChatScreen,并在HomeScreen中通过Button导航到该页面:
class ChatScreen extends React.Component {
static navigationOptions = {
title: 'Chat with Lucy',
};
render() {
return (
<View>
<Text>Chat with Lucy</Text>
</View>
);
}
}
class HomeScreen extends React.Component {
static navigationOptions = {
title: 'Welcome',
};
render() {
const { navigate } = this.props.navigation;
return (
<View>
<Text>Hello, Chat App!</Text>
<Button
onPress={() => navigate('Chat')}
title="Chat with Lucy"
/>
</View>
);
}
}
const SimpleApp = StackNavigator({
Home: { screen: HomeScreen },
Chat: { screen: ChatScreen },
});
参数传递
在页面跳转时,经常需要传递参数。使用react-navigation传递参数非常简单,只需在navigate方法中添加一个JSON对象:
navigate('Chat', { user: 'Lucy' })
在接收页面中,可以通过this.props.navigation.state.params获取参数:
class ChatScreen extends React.Component {
static navigationOptions = {
title: ({ state }) => `Chat with ${state.params.user}`,
};
render() {
const { params } = this.props.navigation.state;
return (
<View>
<Text>Chat with {params.user}</Text>
</View>
);
}
}
TabNavigator使用
TabNavigator用于实现底部导航效果。以下是一个配置示例:
const Tabs = TabNavigator({
Home: {
screen: Home,
navigationOptions: {
tabBar: {
label: '首页',
icon: ({tintColor}) => (<Image source={require('./app/images/home.png')} style={[{tintColor: tintColor},styles.icon]}/>),
},
}
},
Bill: {
screen: Bill,
navigationOptions: {
tabBar: {
label: '账单',
icon: ({tintColor}) => (<Image source={require('./app/images/bill.png')} style={[{tintColor: tintColor},styles.icon]}/>),
},
}
},
Me: {
screen: Me,
navigationOptions: {
tabBar: {
label: '我',
icon: ({tintColor}) => (<Image source={require('./app/images/me.png')} style={[{tintColor: tintColor},styles.icon]}/>),
},
}
}
}, {
animationEnabled: false,
tabBarPosition: 'bottom',
swipeEnabled: false,
backBehavior: 'none',
tabBarOptions: {
activeTintColor: '#ff8500',
inactiveTintColor: '#999',
showIcon: true,
indicatorStyle: { height: 0 },
style: { backgroundColor: '#fff' },
labelStyle: { fontSize: 10 },
},
});
DrawerNavigator使用
DrawerNavigator实现抽屉侧滑效果。配置示例如下:
const DrawerNav = DrawerNavigator({
Home: { screen: Home },
Bill: { screen: Bill },
Me: { screen: Me },
}, {
drawerWidth: 200,
drawerPosition: 'left',
contentOptions: {
activeTintColor: 'white',
activeBackgroundColor: '#ff8500',
inactiveTintColor: '#666',
inactiveBackgroundColor: '#fff',
}
});
iOS版设置注意事项
在iOS中使用react-navigation时,需进行以下设置:
- 在Xcode中配置Schemes。
- 在AppDelegate.m中添加代码处理深层链接:
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { return [RCTLinkingManager application:application openURL:url sourceApplication:sourceApplication annotation:annotation]; } - 在js组件注册路由时设置唯一路径,例如
Home2: { screen: Home2, path:’app/Home2’ }。 - 通过URL如
demo4://app/Home2可以打开应用并跳转到对应页面。
react-native-tab-navigator简介
除了react-navigation,还有一个常用的库react-native-tab-navigator,可用于实现标签导航。以下是一个基本示例代码结构:
import React, { Component } from 'react';
import TabNavigator from 'react-native-tab-navigator';
import { AppRegistry, StyleSheet, Text, Image, View } from 'react-native';
const TabNavigatorItem = TabNavigator.Item;
// 定义图标路径
const TAB_HOME_NORMAL = require('./image/tabbar_homepage.png');
const TAB_MINE_NORMAL = require('./image/tabbar_mine.png');
const TAB_HOME_PRESS = require('./image/tabbar_homepage_selected.png');
const TAB_MINE_PRESS = require('./image/tabbar_mine_selected.png');
export default class HelloWord extends Component {
constructor(){
super();
this.state={
selectedTab:'Home',
}
}
onPress(tabName){
if(tabName){
this.setState({
selectedTab:tabName,
}
);
}
}
renderTabView(title, tabName, tabContent, isBadge){
var tabNomal, tabPress;
switch (tabName) {
case 'Home':
tabNomal = TAB_HOME_NORMAL;
tabPress = TAB_HOME_PRESS;
break;
case 'Mine':
tabNomal = TAB_MINE_NORMAL;
tabPress = TAB_MINE_PRESS;
break;
default:
}
return(
<TabNavigatorItem
selected={this.state.selectedTab === tabName}
title={title}
titleStyle={styles.tabText}
selectedTitleStyle={styles.selectedTabText}
renderIcon={() => <Image style={styles.icon} source={tabNomal}/>}
renderSelectedIcon={() => <Image style={styles.icon} source={tabPress}/>}
onPress={() => this.onPress(tabName)}
renderBadge={() => isBadge ? <View style={styles.badgeView}><Text style={styles.badgeText}>15</Text></View> : null}
>
<View style={styles.page}><Text>{tabContent}</Text></View>
</TabNavigatorItem>
);
}
tabBarView(){
return (
<TabNavigator tabBarStyle={styles.tab}>
{this.renderTabView('首页','Home','首页模块',true)}
{this.renderTabView('我的','Mine','我的模块',false)}
</TabNavigator>
);
}
render() {
var tabView = this.tabBarView();
return (
<View style={styles.container}>
{tabView}
</View>
);
}
}
// 样式定义
const styles = StyleSheet.create({
container: { flex: 1 },
tabText: { fontSize: 10, color: 'black' },
selectedTabText: { fontSize: 10, color: 'green' },
tab: { height: 52, alignItems:'center', backgroundColor:'#f4f5f6' },
badgeView: { width:22, height:14, backgroundColor:'#f85959', borderWidth:1, marginLeft:10, marginTop:3, borderColor:'#FFF', alignItems:'center', justifyContent:'center', borderRadius:8 },
badgeText: { color:'#fff', fontSize:8 },
icon: { width: 22, height: 22 },
page: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#FFFFFF' },
});
AppRegistry.registerComponent('HelloWord', () => HelloWord);
本文介绍了React Native中导航的基本概念、react-navigation库的详细使用方法,以及参数传递和常见导航器的配置。通过合理使用这些导航组件,可以高效地构建复杂的移动应用界面。