在2017年1月,新开源的react-navigation库备受瞩目。它有类似于原生版性能的体验效果,可能会成为未来RN导航组件中的主力军。该库包含三类组件: (1)StackNavigator:用来跳转页面和传递参数。stack就是数据结构的堆栈技术,遵循后进先出的原理。 (2)TabNavigator:类似底部导航栏,用来在同一屏幕下切换不同界面 (3)DrawerNavigator:侧滑菜单导航栏,用于轻松设置带抽屉导航的屏幕
以下属性配合导航使用
npm install react-navigation --save
当然,也可以采用yarn工具将该库添加到项目中
yarn add react-navigation
import {StackNavigator} from 'react-navigation';
import HomeScreen from './HomeScreen'; //导入需要展示的页面
const Navigator = StackNavigator(
//设置导航要展示的页面
{
HomeScreen:{screen:HomeScreen}
},
//设置navigationOptions属性对象
{
navigationOptions: {
title: '标题', //在导航中显示的标题内容
headerBackTitle:null,
headerTintColor:'#333333',
showIcon:true,
swipeEnabled:false,
animationEnabled:false,
},
mode:'card', //设置mode属性
}
);
export default class App extends Component<{}> {
render() {
return (
<Navigator/>
);
}
}
import React, { Component } from 'react';
import {
Platform,
StyleSheet,
AppRegistry,
Text,
View
} from 'react-native';
export default class HomeScreen extends Component {
render(){
return(
<View style={{flex:1,backgroundColor:'pink'}}>
<Text>你好啊 在干嘛呢</Text>
</View>
);
}
}
下面可以来做导航的跳转操作 为了实现跳转操作的功能,需要先新建一个页面,并且将这个页面添加到导航中去。
import ChatScreen from './ChatScreen' //新建的文件
const Navigator = StackNavigator(
{
HomeScreen:{screen:HomeScreen},
ChatScreen:{screen:ChatScreen} //这是新添加的导航界面
只要界面加入到了导航当中,组件中就会自动添加navigation的navigate属性。使用该属性可以跳转到下一个界面。下面是HomeScreen中的代码。ChatScreen是第二个导航界面。在HomeScreen中添加一个button组件,使用routeName路由名称ChatScreen关联到组件ChatScreen.
export default class HomeScreen extends Component {
render(){
return(
<View style={{flex:1,backgroundColor:'pink'}}>
<Text>你好啊 在干嘛呢</Text>
<Button
onPress={()=>this.props.navigation.navigate('ChatScreen')}
title={"chat with lucy"}
/>
</View>
);
}
}
当第二个界面想要回归到上一个界面时,也要用到navigation的goBack属性。当然导航有自身的返回按钮。以下代码是ChatScreen组件的代码,当用户组件Text也会返回到上一个界面。
export default class ChatScreen extends Component {
static navigationOptions = {
title: 'Chat with Lucy',
};
render() {
return (
<View>
<Text onPress={()=>this.props.navigation.goBack()}>Chat with Lucy</Text>
</View>
);
}
}
export default class HomeScreen extends Component {
render(){
const { navigate } = this.props.navigation;
return(
<View style={{flex:1,backgroundColor:'pink'}}>
<Text>你好啊 在干嘛呢</Text>
<Button
onPress={()=>navigate('ChatScreen',{user:'dudu'})}
title={"chat with lucy"}
/>
</View>
);
}
}
之后可以编辑ChatScreen组件显示的user参数,这个参数通过route来传递。为了代码的健壮性,如果外界的user属性有值,就将user赋值给title。如果没有则让title为空。 设置导航右边的菜单,设置一个“返回”的文字
static navigationOptions =({ navigation, screenProps }) => ({
title: navigation.state.params?navigation.state.params.user:null,
headerRight:(
<Text onPress={navigation.state.params?navigation.state.params.navigatePress:null}>
返回
</Text>
)
});
我们也可以将外界的参数传递给函数内部。下面的代码采用结构赋值的方法,取出导航中状态机的参数params,取出参数中的user,一样可以拿到外界参数。
render() {
const {params} = this.props.navigation.state;
return (
<View>
<Text onPress={()=>this.props.navigation.goBack()}>Chat with {params.user}</Text>
</View>
);
}
react-navigation组件除了可以用做页面间的跳转,当然也可以用做tab界面之间的切换。
import {StackNavigator,TabNavigator,TabBarBottom} from 'react-navigation';
import React,{Component} from 'react';
import {Image} from 'react-native';
export default class TabBarItem extends Component {
render() {
return(
<Image source={ this.props.focused ? this.props.selectedImage : this.props.normalImage }
style={ { tintColor:this.props.tintColor,width:25,height:25 } }
/>
)
}
}
import TabBarItem from './TabBarItem';
const Tab = TabNavigator({
Home:{
screen:HomeScreen,
navigationOptions:({navigation}) => ({
tabBarLabel:'首页',
tabBarIcon:({focused,tintColor}) => (
<TabBarItem
tintColor={tintColor}
focused={focused}
normalImage={require('./imgs/ic_like_sel.png') }
selectedImage={require('./imgs/ic_mine_sel.png')}
/>
)
}),
},
Mine:{
screen:MineScreen,
navigationOptions:({navigation}) => ({
tabBarLabel:'我',
tabBarIcon:({focused,tintColor}) => (
<TabBarItem
tintColor={tintColor}
focused={focused}
normalImage={require('./imgs/ic_like_sel.png')}
selectedImage={require('./imgs/ic_like_sel.png')}
/>
)
}),
},
},
{
tabBarComponent:TabBarBottom,
tabBarPosition:'bottom',
swipeEnabled:false,
animationEnabled:false,
lazy:true,
tabBarOptions:{
activeTintColor:'#06c1ae',
inactiveTintColor:'#979797',
style:{backgroundColor:'#ffffff',},
labelStyle: {
fontSize: 20, // 文字大小
},
}
});
const Navigator = StackNavigator(
{
Tab:{screen:Tab},
},
{
navigationOptions:{
// title:'首页',
headerBackTitle:null,
headerTintColor:'#333333',
showIcon:true,
swipeEnabled:false,
animationEnabled:false,
},
mode:'card',
});
export default class App extends Component<{}> {
render() {
return (
<Navigator/>
);
}
}
StackNavigator还提供了onNavigationStateChange回调方法,用来监听导航状态的改变
import React, { Component } from 'react';
import {
Platform,
StyleSheet,
Text,
View
} from 'react-native';
export default class HomePage extends Component {
static navigationOptions = {
title:'首页',
};
render() {
return(
<View style={{flex:1,backgroundColor:'yellow'}}>
<Text onPress={this._skip.bind(this)}>点击跳转</Text>
</View>
);
}
_skip() {
this.props.navigation.navigate("Mine");
}
}
import React, { Component } from 'react';
import {
Platform,
StyleSheet,
Text,
View
} from 'react-native';
export default class MinePage extends Component {
static navigationOptions = {
title:'我',
};
render() {
return(
<View style={{flex:1,backgroundColor:'pink'}}>
<Text onPress={this._skip.bind(this)}>MinePage</Text>
</View>
);
}
/**
* 跳转
*/
_skip() {
this.props.navigation.goBack();
}
}
DrawerNavigator是一个抽屉导航。设置方式其实跟设置Tab差不多。只是需要设定某些特殊的属性。比如说drawerLabel、drawerIcon、drawerWidth、drawerPosition等等。
import {DrawerNavigator} from 'react-navigation';
import HomeScreen from './Pages/HomePage';
import MineScreen from './Pages/MinePage';
const MyApp = DrawerNavigator({
Home: {
screen: HomeScreen,
},
Mine: {
screen:MineScreen,
},
},
{
drawerWidth: 200, // 抽屉宽
drawerPosition: 'left', // 抽屉在左边还是右边
contentOptions: {
initialRouteName: 'Home', // 默认页面组件
activeTintColor: 'white', // 选中文字颜色
activeBackgroundColor: '#ff8500', // 选中背景颜色
inactiveTintColor: '#666', // 未选中文字颜色
inactiveBackgroundColor: '#fff', // 未选中背景颜色
style: { // 样式
}
}
}
);
export default class App extends Component<{}> {
// static navigationOptions={
// title:'app',
// gesturesEnabled:false,
// header:null,
// }
render() {
return (
<View style = {{flex:1,marginTop:20,}}>
<MyApp />
</View>
);
}
}
export default class HomePage extends Component<{}> {
static navigationOptions = {
drawerLabel: 'Home',
drawerIcon: ({ tintColor }) => (
<Image
source={require('.././imgs/ic_like_sel.png')}
style={[styles.icon, {tintColor: tintColor}]}
/>
),
};
}
render() {
return (
<View>
<Button
onPress={() => this.props.navigation.navigate('Mine')}
title="Go to Mine"
/>
<Button
onPress={()=>this.props.navigation.navigate('DrawerOpen')}
title="open the draw"
/>
</View>
);
}
const styles = StyleSheet.create({
icon: {
width: 24,
height: 24,
},
});
import React, { Component } from 'react';
import {
Platform,
StyleSheet,
Text,
View,
Image,
Button
} from 'react-native';
export default class MineScreen extends Component<{}> {
static navigationOptions = {
drawerLabel: 'Mine',
drawerIcon: ({ tintColor }) => (
<Image
source={require('.././imgs/ic_mine_sel.png')}
style={[styles.icon, {tintColor: tintColor}]}
/>
),
};
render() {
return (
<View>
<Button
onPress={() => this.props.navigation.goBack()}
title="Go back home"
/>
<Button
onPress={()=>this.props.navigation.navigate('DrawerOpen')}
title="open the draw"
/>
</View>
);
}
}
const styles = StyleSheet.create({
icon: {
width: 24,
height: 24,
},
});
效果图如下:
非宁静无以致远,非淡泊无以明志。在学习的道路上,多少会遇到泥泞挫折。我可以放慢脚步,但绝能不回头,我的梦想,在路上。