React Native 关于界面导航

本篇文章只讲解基础用法,如果你想了解更多,请戳这里->戳我

简介

react-navigation主要包括导航,底部tab,顶部tab,侧滑等,功能很强大,而且体验接近原生。今天我们介绍的组件分别为:

  • 导航 -> StackNavigator
  • 底部或者顶部tab -> TabNavigator
  • 侧滑 -> DrawerNavigator

DrawerNavigator

先来看看运行效果:



这里,我们定义三个界面,一个为根界面,一个主界面,一个侧滑界面,分别如下:

侧滑界面DrawerLeftPage.js:

 
     
import React, {Component} from 'react';
import {
View,
Text,
TouchableOpacity,
StyleSheet,
Image
} from 'react-native';
export default class DrawerLeftPage extends Component {
static navigationOptions = {
//标题
drawerLabel: '购物车',
//图标
drawerIcon:({tintColor}) => {
return (
<Image
source= {require(' ../ images/ car@ 3x.png')}
style= {[{width:24,height:24},{tintColor:tintColor}]}
/>
);
},
};
render() {
return(
<View style={styles.container}>
<TouchableOpacity onPress={()=>{
//点击关闭侧滑
this.props.navigation.navigate('DrawerClose')
}}>
<Text>关闭侧滑栏 </Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex:1,
justifyContent:'center',
alignItems:'center'
}
});

这个界面很简单,我们定义了一个按钮,点击按钮的时候,关闭侧滑页,这里关闭的参数为DrawerClose,通过props属性可以拿到当前navigation。另外我们又定义了一个静态属性,来配置侧滑显示的具体属性。注意,此属性名一定要写成navigationOptions

navigationOptions主要有以下参数:

  • title:通用标题,当你不写drawerLabel时,使用此参数作为侧滑标题,通常都不写
  • drawerLabel:侧滑标题
  • drawerIcon:侧滑的标题图标,这里会回传两个参数,{focused: boolean, tintColor: string}focused表示是否是选中状态,tintColor表示选中的颜色,这个颜色是我们自己在根视图定义的。当然,你也可以使用其他的组件来作为图标,比如Text

主界面 DrawerHomePage.js

 
     
import React, {Component} from 'react';
import {
View,
Text,
TouchableOpacity,
StyleSheet,
Image
} from 'react-native';
export default class DrawerHomePage extends Component {
static navigationOptions = {
drawerLabel: '首页',
drawerIcon:({tintColor}) => {
return (
<Image
source= {require(' ../ images/ home@ 3x.png')}
style= {[{width:24,height:24},{tintColor:tintColor}]}
/>
);
},
};
render() {
return(
<View style={styles.container}>
<TouchableOpacity onPress={()=>{
//点击打开抽屉
this.props.navigation.navigate('DrawerOpen')
}}>
<Text>打开侧滑栏 </Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex:1,
justifyContent:'center',
alignItems:'center'
}
});

这个界面和上一个界面基本一样,只是这里的点击事件为打开抽屉,传的参数为DrawerOpen
打开侧滑:this.props.navigation.navigate('DrawerOpen')
关闭侧滑:this.props.navigation.navigate('DrawerClose')

根视图 DrawerPage.js

 
     
import React, {Component} from 'react';
import {
StyleSheet,
View
} from 'react-native';
import DrawerHomePage from './DrawerHomePage';
import DrawerLeftPage from './DrawerLeftPage';
import {DrawerNavigator} from 'react-navigation';
const Drawer = DrawerNavigator(
{
Home:{
screen:DrawerHomePage,
},
Left:{
screen:DrawerLeftPage
}
},
{
drawerWidth: 300,
drawerPosition: 'left',
}
);
export default class DrawerPage extends Component {
render() {
return(
<Drawer/>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
}
});

这里我们从react-navigation导入侧滑组件DrawerNavigator,这里我们定义一个常量Drawer,主要来配置侧滑的各种参数。首先,看DrawerNavigator的构造方法:
DrawerNavigator(RouteConfigs, DrawerNavigatorConfig)
这里接收两个参数,一个为页面路由配置,一个为显示的配置,我们分别来看,

RouteConfigs

这里你可以配置所有的界面,例如,当前例子配置了两个界面:HomeLeft,指定界面分别为DrawerHomePageDrawerLeftPage。你还可以配置其他界面,这些配置的界面都将显示在侧滑栏上。

DrawerNavigatorConfig

  • drawerWidth: 侧滑栏的宽度,如果你不想写死,可以使用Dimensions获取屏幕的宽度,动态计算
  • drawerPosition: 侧滑的方向,leftright,默认left
  • contentComponent: 这个就比较重要了,可以自定义侧滑页,我们等会详细说。
  • contentOptions: 主要配置侧滑栏条目的属性,只对DrawerItems,例如我们刚才写的例子,就可以通过这个属性来配置颜色,背景色等。其主要属性有:
    • items: 这个我也没弄清是什么意思,不影响
    • activeItemKey: 定义当前选中的页面的key
    • activeTintColor: 选中条目状态的文字颜色
    • activeBackgroundColor: 选中条目的背景色
    • inactiveTintColor: 未选中条目状态的文字颜色
    • inactiveBackgroundColor: 未选中条目的背景色
    • onItemPress: 选中条目的回调,这个参数属性为函数,会将当前路由回调过去
    • style: 定义条目的颜色
    • labelStyle: 定义条目文字的颜色

例如:

 
     
{
drawerWidth: 300,
drawerPosition: 'left',
contentOptions:{
activeTintColor: '#e91e63',
items:[ "Home"],
activeItemKey: 'abc',
activeBackgroundColor: 'yellow',
inactiveTintColor: 'blue',
inactiveBackgroundColor: 'red',
onItemPress:((route)=>{
console.log(route);
}),
labelStyle:{
fontSize: 30
},
style:{
marginRight: 30
}
}
}

如此,DrawerNavigator的基本用法我们已经搞的差不多了,但是,这还不能满足我们的日常开发,因为我们的侧滑界面可不是这个样子的。

刚才还有个参数没有介绍,就是contentComponent,他就是用来自定义侧滑界面的。

上面的例子有一个问题,加入我们的item比较多,但是侧滑页面并不能滑动,这时,就要使用contentComponent来自定义界面,如下:

 
     
//导入DrawerItems 因为系统的条目就是DrawerItems
import {DrawerNavigator,DrawerItems} from 'react-navigation';
{
drawerWidth: 300,
drawerPosition: 'left',
//ScrollView作为我们的侧滑界面,内部依然是DrawerItems
contentComponent:((props)=>{
return(
<ScrollView style={styles.container} >
<DrawerItems {...props}/>
</ScrollView>
)})
}

运行效果如下:



当然,我们完全可以自定义侧滑界面,并且不使用DrawerItems条目。如下:

 
     
import DrawerHomePage from './DrawerHomePage';
import DrawerLeftPage from './DrawerLeftPage';
import {DrawerNavigator} from 'react-navigation';
//自定义侧滑界面
const CustomDrawerContentComponent = (props)=>{
return(
<DrawerLeftPage style={styles.container} {...props} />
);
};
const Drawer = DrawerNavigator(
{
Home:{
screen:DrawerHomePage,
}
},
{
drawerWidth:300,
drawerPosition:'left',
contentComponent:(CustomDrawerContentComponent)
}
);
export default class DrawerPage extends Component {
render() {
return(
<Drawer/>
);
}
}
const styles = StyleSheet.create({
container: {
flex:1
}
});

我们这里定义了一个常量,返回DrawerLeftPage作为我们的侧滑界面,在DrawerLeftPage中就可以随意定制了。注意,一定要将props传递到下一个界面,否则通过props拿不到navigation。最终运行效果:



好了,DrawerNavigator我们已经了解完了。


StackNavigator

这个组件就比较麻烦了,我们先来看他的构造函数:
StackNavigator(RouteConfigs, StackNavigatorConfig)

RouteConfigs:

它主要是来配置页面路由的,类似与AndroidManifest.xml,所有的界面都必须配置在里面。如下:

 
     
{
First:{
screen:FirstNavigation,
navigationOptions:({
title: '首页'
})
},
Second:{
screen:SecondNavigation,
navigationOptions:({navigation}) => ({
title: "第二个界面"
})
}
}

这里我们配置了首页和第二个页面,并且配置了标题参数。当然,如果你不想在路由里面配置页面的参数,你也可以在页面中配置,需要在页面中定义一个静态常量navigationOptions,和DrawerNavigator的使用方法类似。我们来看看navigationOptions有哪些可以配置的参数:

  • title: 这个即可以作为头部标题,也可以作为返回标题和Tab标题
  • header: 自定义导航条,系统的导航条会隐藏
  • headerTitle: 标题
  • headerBackTitle: 回退标题
  • headerTruncatedBackTitle: 当回退标题不能显示的时候显示此属性的标题,比如回退标题太长了
  • headerRight: 定义导航栏右边视图
  • headerLeft: 定义导航栏左边视图
  • headerStyle: 定义导航栏的样式,比如背景色等
  • headerTitleStyle: 定义标题的样式
  • headerBackTitleStyle: 定义返回标题的样式
  • headerTintColor: 定义导航条的tintColor,会覆盖headerTitleStyle中的颜色
  • gesturesEnabled: 定义是否能侧滑返回,iOS默认trueAndroid默认false

示例如下:

 
     
static navigationOptions=({
title: '首页',
header:(
<View style={{width:Dimensions.get('window').width,height:64,backgroundColor:'red'}}/>
),
headerTitle:(
<View style={{width:60,height:20,backgroundColor:'red'}}/>
),
headerBackTitle:'哈哈哈哈哈',
headerTruncatedBackTitle:'你好',
headerRight:(
<View>
<Text>right</Text>
</View>
),
headerLeft:(
<View>
<Text>left</Text>
</View>
),
headerStyle: {
backgroundColor:'yellow'
},
headerTitleStyle:{
color:'red'
},
headerBackTitleStyle:{
tintColor:'#789'
},
headerTintColor:'#956',
gesturesEnabled:false
});

StackNavigatorConfig

这个参数主要是配置整个路由的,包括跳转动画,跳转方式等。先来看看它有哪些参数:

  • initialRouteName: 初始化哪个界面为根界面,如果不配置,默认使用RouteConfigs中的第一个页面当做根界面
  • initialRouteParams: 初始化根界面参数,主要是给根视图传递一些参数,通过this.props.navigation.state.params可以取到
  • navigationOptions: 配置默认的navigationOptions
  • paths: 官方意思是覆盖已经配置的路由,可是我没有试出来效果
  • mode: 跳转方式,一种是card,默认的,在iOS上是从右到左跳转,在Android上是从下到上,都是使用原生系统的默认跳转方式。一种是modal,只针对iOS平台,模态跳转。
  • headerMode: 跳转过程中,导航条的动画效果,有三个值,float表示会渐变,类似于iOS的原生效果,screen表示没有渐变。none表示隐藏导航条
  • cardStyle: 可以统一定义界面的颜色,例如背景色
  • transitionConfig:配置页面跳转的动画
  • onTransitionStart: 页面跳转动画即将开始的回调
  • onTransitionEnd: 页面跳转动画结束的回调
 
     
static stackNavigatorConfig = ({
initialRouteName: 'First',
initialRouteParams:{
data: 'haha'
},
navigationOptions:{
headerTintColor: 'red'
},
mode: 'card',
headerMode: 'screen',
cardStyle:({backgroundColor: 'blue'}),
onTransitionStart:((route)=>{
console.log( '开始动画');
}),
onTransitionEnd:((route)=>{
console.log( '结束动画');
}),
transitionConfig:(()=>({
//因为ios 的导航动画默认是从左到右,所以,这里配置一下动画,使用react-navigation已经实现的从左到右的动画,
//适配Android,不过,需要导入动画
//import CardStackStyleInterpolator from 'react-navigation/src/views/CardStackStyleInterpolator';
screenInterpolator:CardStackStyleInterpolator.forHorizontal,
}))
});

Navigation Prop

了解完路由配置以后,我们再来看看组件的属性,

  • navigate:路由方法,主要来启动另一个页面
  • state:状态,其实StackNavigator内部维护了两个路由栈,一个名为newState,是当前显示页面之前的所有页面,包括当前界面。一个名为lastState,当然,通过state还能拿到很多参数。
  • setParams: 设置参数,记住,一定不要在render方法中调用此方法。
  • goBack: 返回
  • dispatch: 给当前界面设置action,会替换原来的跳转,回退等事件

navigate

此方法可以传三个参数:navigate(routeName, params, action)

  • routeName: 页面名称,一定要在路由配置中配置。
  • params: 传递参数到下一个页面
  • actionaction

例如:

 
     
this.props.navigation.navigate( 'Second',{ 'data': 'haha'});

state

通过state,我们能拿到传递过来的参数,通过打印state,得到如下结果:

 
     
state:
{ params: { 'data': 'haha'},
key: 'id-1495292939049-1',
routeName: 'Model' }

可以看到,通过state,我们可以拿到传递过来的params

setParams

设置当前页面的参数,记住,调用此方法一定要在componentDidMount

 
     
componentDidMount() {
var {setParams} = this.props.navigation;
setParams({ 'haha': 'abc'});
}

goBack

回退到指定界面,如果什么都不传,回退到上一个界面,传null,回退到任意界面。传key,可以回退到指定界面。例如:

 
     
this.props.navigation.goBack();
this.props.navigation.goBack( null);
this.props.navigation.goBack( 'Profile');

关于react-navigation的基本用法已经了解的差不多了,至于更详细的用法,可以看官方文档。

注意:

全屏侧滑返回手势:系统默认有侧滑返回手势,距离屏幕距离为35,为了使用全屏侧滑,需要修改源码:在react-navigation/src/views/CardStack.js类,修改常量GESTURE_RESPONSE_DISTANCE_HORIZONTALDimensions.get('window').width即可。

iOS上,标题会居中,但是在Android上是居左的,想要Android上也居中,需要修改:react-navigation/src/views/Header.js中的title样式修改为center,并且在方法_renderTitle中注释掉

 
     
if (Platform.OS === 'android') {
if (!options.hasLeftComponent) {
style.left = 0;
}
if (!options.hasRightComponent) {
style.right = 0;
}
}

这几句代码。


TabNavigator

tab选项卡的功能,在iOS上默认类似于TabBar,在Android中类似于TabLayout,先来看看构造方法:

 
     
TabNavigator(RouteConfigs, TabNavigatorConfig)

RouteConfigs

同样的,还是配置路由,如下:

 
     
{
Home:{
screen:HomeTab,
//navigationOptions:{
// ....
//}
},
Car:{
screen:CarTab
},
Profile:{
screen:ProfileTab
}
}

当然,你也可以配置navigationOptions,但是,在这里配置的优先级比在页面中配置的优先级高,所以,我们一般再单个页面中配置所有的navigationOptions

TabNavigatorConfig

  • tabBarComponent: 默认两种方式,TabBarBottomTabBarTop,可以通过如下代码导入:import {TabBarBottom,TabBarTop} from 'react-navigation';,这两者的区别主要是样式和位置的区别,iOS上默认使用TabBarBottomAndroid上默认使用TabBarTop
  • tabBarPosition: 配置tab的位置,topbottom
  • swipeEnabled: 是否可以滑动切换tab
  • animationEnabled: 点击选项卡切换界面是否需要动画
  • lazy: 是否懒加载界面,默认一次加载所有的界面,我们最好设置为true
  • tabBarOptionstab的样式等配置,我们下面详细说
  • initialRouteName,第一次初始化哪个界面,默认初始化第一个。
  • ordertab排序,默认使用配置路由的顺序
  • paths: 配置path
  • backBehavior,当Android点击返回键的时候,做的处理,initialRoute返回到初始化的界面,none退出应用

例子如下:

 
     
const Tab = TabNavigator(
{
Home:{
screen:HomeTab
},
Car:{
screen:CarTab
},
Profile:{
screen:ProfileTab
}
},
{
tabBarComponent:TabBarBottom,
tabBarPosition: 'bottom',
swipeEnabled: true,
animationEnabled: false,
lazy: true,
initialRouteName: 'Profile',
order:([ 'Profile', 'Home', 'Car']),
backBehavior: 'none'
}
);

tabBarOptions

这个参数主要配置样式,针对TabBarBottomTabBarTop

TabBarBottom:

  • activeTintColor: 选中的文字颜色
  • activeBackgroundColor: 选中的背景色
  • inactiveTintColor: 未选中的文字颜色
  • inactiveBackgroundColor: 未选中的背景色
  • showLabel: 是否显示标题,默认显示
  • style: 定义item的样式
  • labelStyle: 标题的样式

例如:

 
     
tabBarOptions:{
activeTintColor: 'red',
activeBackgroundColor: 'blue',
inactiveTintColor: 'yellow',
inactiveBackgroundColor: '#987',
showLabel: true,
labelStyle:{
fontSize: 12
}
}

TabBarTop:

  • activeTintColor: 选中的文字颜色
  • inactiveTintColor: 未选中的文字颜色
  • showIcon: 是否显示图标,默认显示
  • showLabel: 是否显示标题,默认显示
  • upperCaseLabel: 使用大写字母
  • pressColor: 定义颜色,大于Android5.0的一种按压效果
  • pressOpacity: 按压下去的透明度,在iOS或者Android5.0之前
  • scrollEnabled: 是否能够滚动,类似于今日头条的标题头
  • tabStyle: 定义item的样式
  • indicatorStyle: 指示器的颜色
  • labelStyle: 文字的样式
  • iconStyle: 图标的样式
  • style: 定义tab的样式

例如:

 
     
tabBarOptions:{
activeTintColor: 'red',
inactiveTintColor: 'yellow',
showIcon: false,
showLabel: true,
upperCaseLabel: false,
labelStyle:{
fontSize: 12
},
indicatorStyle: 'green',
pressColor: '#823453',
pressOpacity: 0.8,
scrollEnabled: true,
tabStyle:{
height: 44
}
}

NavigationOptions

当然,通过NavigationOptions来配置我们的tabBarItem:

  • title: 标题
  • tabBarVisible: 是否可见
  • tabBarIcon: 配置图片,当然,完全可以不使用图片
  • tabBarLabel: 也是配置标题,只不过title既能配置tab的标题,也能配置navigation的标题

例如:

 
     
Profile:{
screen:ProfileTab,
navigationOptions:({navigation})=>({
tabBarLabel: '我的',
tabBarIcon:({focused,tintColor})=>(
<Image
source= {focused?require(' ../ ../ images/ user_hover@ 3x.png') :require(' ../ ../ images/ user@ 3x.png')}
style= {{width:30,height:30,tintColor:tintColor}}
/>
)
}),
}

好了,TabNavigator也说的差不多了。当然,如果你想在某个界面切换tab,使用如下方法:

 
     
this.props.navigation.navigate( 'Home')

下面的例子是仿QQ主界面的,当然包括本篇文章的实例代码,请戳这里->戳我

转自:点击打开链接

猜你喜欢

转载自blog.csdn.net/s349856186/article/details/80262791