RN导航组件 React Navigation 使用,最新版本及更多使用详解可查看官方文档。
Step1:创建导航
创建createMaterialTopTabNavigator组件
//TopNavigatorComponent.js
import {createAppContainer, createMaterialTopTabNavigator} from 'react-navigation'
import TopPage1 from './TopPage1'
import TopPage2 from './TopPage2'
import TopPage3 from './TopPage3'
import TopPage4 from './TopPage4'
/**
* 标签导航
*/
const TopTabNavigator = createMaterialTopTabNavigator({
topPage1: {
screen: TopPage1,
},
topPage2: {
screen: TopPage2,
},
topPage3: {
screen: TopPage3,
},
topPage4:{
screen:TopPage4,
}
}, {
tabBarPosition: 'bottom', //标签栏在屏幕顶部还是底部
// swipeEnabled:true, //是否可以滑动切换标签
// backBehavior:'none', //andorid按下返回键将返回initalRouteName,如果设置非initalRouteName则直接结束标签导航
lazy: false, //是否只渲染显示的标签
animationEnabled: true, //标签切换是否有动画效果
tabBarOptions: {
activeTintColor: '#ffffff', //标签栏激活字体颜色
inactiveTintColor: '#000000',//标签栏未激活字体颜色
showLabel: true, //是否显示标签栏
labelStyle: {fontSize: 16}, //标签样式(可设置字体大小等)
showIcon: true, //是否显示标签栏上图标
scrollEnabled: true, //是否可以滚动标签栏目(当tab总数超过一屏)
indicatorStyle: {height: 1}, //指示器样式 height:0则不显示
style: {backgroundColor: '#31b3c0'}, //设置整个tabbar样式(背景颜色等)
// tabStyle:{backgroundColor:'#ffffff', height:50},//设置单个tabbar样式
}
});
const appTopTabNavigation = createAppContainer(TopTabNavigator);
export default appTopTabNavigation;
TopTabBar某个tab实现页面(TopPage2.js)
import React, {Component} from 'react';
import {View, Text, Image, ToastAndroid,TouchableOpacity} from 'react-native';
export default class TopPage2 extends Component {
static navigationOptions = ({navigation}) => ({
tabBarLabel: '推荐专题',
tabBarIcon: ({focused, tintColor}) => {
return <Image style={{height: 20, width: 20, tintColor: tintColor}}
source={require('../../images/hot.png')}/>
},
tabBarOnPress: (event) => {
event.defaultHandler();
ToastAndroid.show('选项卡二被点击了', 1000);
}
})
render() {
console.log('page2 =========render');
return (<View style={{flex: 1, backgroundColor: '#94ad24', justifyContent: 'center', alignItems: 'center'}}>
<Text style={{color: '#fdfdff', fontSize: 30}}>TopNavigation—推荐专题</Text>
<TouchableOpacity onPress={this.jumpOutTabBar.bind(this)}>
<Text style={{color: '#fffefd', fontSize:16,marginTop:15,padding:5,borderRadius:5,borderWidth:1,borderColor:'#fff'}}>跳出标签导航之外页面</Text>
</TouchableOpacity>
</View>);
}
/**
*跳出当前topTabNavigator组件之外指定的页面,此页面需要在StackNavigation定义
*并且需要将TopNavigationComponent嵌套在StackNavigator中,否则无法跳转。
*/
jumpOutTabBar() {
this.props.navigation.navigate('scrollPage');
}
}
将TopNavigatorComponent嵌套到StackNavigator中(也可不嵌套单独使用,根据需求确定)
Index.js中加载
import {AppRegistry} from 'react-native';
//单独使用TopNavigatorComponent
import MTopNavigatorComponent from './UI/navigator_/TopNavigatorComponent'
//将TopNavigatorComponent嵌入到StackNavigator中使用
import MStackNavigatorComponent from './UI/navigator_/StackNavigatorComponent'
import {name as appName} from './app.json';
AppRegistry.registerComponent(appName, () => MStackNavigatorComponent);
![]() | ![]() |
通过指定tabBarOptions属性来实现满足自己需求的导航
先看一下tabBarOptions有哪些属性:
我们可通过这些属性来修改样式满足自己的需求,比如:我需要如下样式的导航(指示器长度非默认充满tab,而是固定长度且圆角居中文字底部显示)
我们可设置indicatorStyle中的width和left以百分比的形式设置值实现:
扩展
此时需求又变更了,我们需要指示器固定长度圆角居中显示在Label下面,而且导航器左侧需要又一个返回按钮,如下:
方案一:通过tabBarIcon实现自定义导航
不足:无法针对某个tab内中多个view做事件监听(如果并不需要实现返回仅需要实现tab可以使用此方式)
我们可以通过自定义navigationOptions——>tabBarIcon中的view来实现(需要createMaterialTopTabNavigator中的tabBarOptions设置配合使用)。
createMaterialTopTabNavigator 配置
const tabNavigation = createMaterialTopTabNavigator({
completeOrder: {
screen: CompleteOrder,
},
auditingOrder: {
screen: AuditingOrder,
},
allOrder: {
screen: AllOrder,
},
}, {
tabBarPosition: 'top', //标签栏在屏幕顶部还是底部
swipeEnabled:true, //是否可以滑动切换标签
lazy: false, //是否只渲染显示的标签
animationEnabled: true, //标签切换是否有动画效果
tabBarOptions: {
/**
* 通过tabBarIcon实现自定义标签和指示器
*/
showIcon: true, //是否显示标签栏上图标
showLabel: false, //是否显示标签栏,通过自定义实现
indicatorStyle: {height: 0,}, //指示器样式 height:0则不显示通过自定义实现
style: {backgroundColor: '#ffffff', height:68}, //设置整个tabbar样式(背景颜色等)
tabStyle:{height:68}, //设置单个tabbar样式
}
}
)
const AppContainer = createAppContainer(tabNavigation);
export default AppContainer;
CompleteOrder页面的navigationOptions实现
import React, {Component} from 'react';
import {View, Text, Dimensions, Image, TouchableOpacity,StyleSheet} from 'react-native';
import CommStyle from '../../style/CommonStyle'
/**
* @Author zhangchao
* @Date: 2019/05/05
* @Desc: 已完成订单...
**/
var screenWidth = Dimensions.get('window').width;
export default class CompleteOrderComponent extends Component {
static navigationOptions = ({navigation}) => ({
/**
* 通过使用tabBarIcon自定义选项卡实现自定义指示器长短
**/
tabBarIcon: ({tintColor, focused}) => (
<View
style={completeOrderStyle.navigatoinBarView}>
<TouchableOpacity onPress={() => {
console.warn('=====click back====');
}}>
<View>
<View style={completeOrderStyle.placeholderView}/>
<View style={completeOrderStyle.backView}>
<Image
style={completeOrderStyle.backIcon}
source={require('../../image/back_icon.png')}/>
</View>
<View style={completeOrderStyle.backPlaceholderView}/>
</View>
</TouchableOpacity>
<View>
<View style={completeOrderStyle.completePlaceholderView}/>
<View style={completeOrderStyle.completeTxView}>
<Text style={[completeOrderStyle.completeTx,{color: focused ? '#F46C20' : '#9499A4',}]}>已完成</Text>
</View>
<View style={[completeOrderStyle.indicatorView,{backgroundColor: focused ? 'rgba(244,108,32,1)' : 'rgba(0,0,0,0)'}]}/>
</View>
</View>
),
/**
* TODO tab点击事件
*/
tabBarOnPress: (event) => {
event.defaultHandler();
}
})
render() {
return (
<View style={[CommStyle.container, Component.tabBar]}>
<Text>已完成订单</Text>
</View>
);
}
}
const completeOrderStyle = StyleSheet.create({
navigatoinBarView:{
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
width: screenWidth / 3,
height: 68,
backgroundColor: '#fff',
},
placeholderView:{
height: 20
},
backView:{
height: 45,
justifyContent: 'center'
},
backIcon:{
marginLeft: 18,
width: 20,
height: 20,
},
backPlaceholderView:{
height: 4,
},
completePlaceholderView:{
height: 20,
backgroundColor: 'rgba(0,0,0,0)'
},
completeTxView:{
height: 45,
justifyContent: 'center',
alignItems: 'center'
},
completeTx:{
textAlign: 'center',
fontSize: 14,
fontWeight: 'bold'
},
indicatorView:{
alignSelf: 'center',
width: 30,
height: 3,
borderRadius: 8,
},
})
其他tab子页面设置和上面一致。
PS:通过自定义tabBarIcon实现方式有个问题,即tab内部多个view点击事件会触发tab的 tabBarOnPress 事件,无法根据控件来定义事件。
其中TouchableOpacity返回按钮事件并不会触发,而是触发tabBarOnPress事件。
不足:无法通过左右滑动切换页面(如果并不需要实现滑动切换页面可以使用此方式)
createStackNavigator配置:(重点在于orderTab的navigationOptions)
const navigationHeigth = 68;
const stautsBarHeight = 20;
let currentIndex = 1;
const StackNavigationComponent = createStackNavigator({
homeTab: {
screen: HomeTab,
navigationOptions: {
header: null,
}
},
login: {
screen: Login,
},
register: {
screen: Register,
},
forgotPwd: {
screen: ForgotPwd,
},
orderTab: {
screen: OrderTab,
/**
* 系统提供的选项卡导航组件无法满足需求,这里通过StackNavigation导航来实现TopTabNavigation导航的选项卡(禁用topTabNavigation滑动)
*/
navigationOptions: ({navigation}) => ({
header:(
<View
style={stackNavigationStyle.statusBar}>
<View
style={stackNavigationStyle.orderCompleteView}>
<TouchableOpacity
style={stackNavigationStyle.orderCompleteBackTouchView}
onPress={() => {
navigation.goBack();
}}>
<Image
style={stackNavigationStyle.orderCompleteBackIcon}
source={require('../image/back_icon.png')}/>
</TouchableOpacity>
<TouchableOpacity
style={stackNavigationStyle.orderCompleteTouchView}
onPress={() => {
navigation.navigate('completeOrder');
currentIndex = 1;
}}>
<Text
style={[stackNavigationStyle.orderCompleteTx, {color: currentIndex === 1 ? '#F46C20' : '#9499A4'}]}>已完成</Text>
<View
style={[stackNavigationStyle.orderCompleteIndicatorView, {backgroundColor: currentIndex === 1 ? '#F46C20' : 'rgba(0,0,0,0)'}]}/>
</TouchableOpacity>
</View>
<TouchableOpacity
style={stackNavigationStyle.orderAuditingTouchView}
onPress={() => {
navigation.navigate('auditingOrder');
currentIndex = 2;
}}>
<Text
style={[stackNavigationStyle.orderAuditingTx, {color: currentIndex === 2 ? '#F46C20' : '#9499A4'}]}>审核中</Text>
<View
style={[stackNavigationStyle.orderAuditingIndicatorView, {backgroundColor: currentIndex === 2 ? '#F46C20' : 'rgba(0,0,0,0)'}]}/>
</TouchableOpacity>
<TouchableOpacity
style={stackNavigationStyle.orderAllTouchView}
onPress={() => {
navigation.navigate('allOrder');
currentIndex = 3;
}}>
<Text
style={[stackNavigationStyle.orderAllTx, {color: currentIndex === 3 ? '#F46C20' : '#9499A4'}]}>全部</Text>
<View
style={[stackNavigationStyle.orderAllIndicatorView, {backgroundColor: currentIndex === 3 ? '#F46C20' : 'rgba(0,0,0,0)'}]}/>
</TouchableOpacity>
</View>
),
//解决IOS关闭页面时候一闪而过默认的返回按钮
headerLeft: null,
})
}
})
const AppContainerComponent = createAppContainer(StackNavigationComponent);
// export default AppContainerComponent;
export default class StackNavigationComponentm extends Component {
render() {
return (<AppContainerComponent/>);
}
}
var stackNavigationStyle = StyleSheet.create({
statusBar: {
height: navigationHeigth,
paddingTop: stautsBarHeight,
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
backgroundColor: '#fff',
},
orderCompleteView: {
flex: 1,
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
},
orderCompleteBackTouchView: {
padding: 5
},
orderCompleteBackIcon: {
width: 20,
height: 20,
marginLeft: 10,
},
orderCompleteTouchView: {
flex: 1,
alignItems: 'flex-end',
paddingTop: 12,
},
orderCompleteTx: {
fontSize: 14,
fontWeight: 'bold',
},
orderCompleteIndicatorView: {
width: 30,
height: 3,
borderRadius: 8,
marginTop: 8,
marginRight: 6,
},
orderAuditingTouchView: {
flex: 1.2,
alignItems: 'center',
paddingTop: 12,
},
orderAuditingTx: {
fontSize: 14,
fontWeight: 'bold',
},
orderAuditingIndicatorView: {
marginTop: 8,
width: 30,
height: 3,
borderRadius: 8,
},
orderAllTouchView: {
flex: 1,
paddingTop: 12,
},
orderAllTx: {
marginRight: 14,
fontWeight: 'bold',
},
orderAllIndicatorView: {
width: 30,
height: 3,
borderRadius: 8,
marginTop: 8,
}
})
OrderTab(createMaterialTopTabNavigator)配置如下
这里将createMaterialTopTabNavigator中的tabBar设置为不可见(高度为0),且禁止滑动切换标签(因为刚入门目前还未找到滑动页面切换监听事件,无法通过页面滑动来更新StackNavigation顶部tab选项卡状态,因此这里禁用滑动切换,只能通过点击tab来切换页面)。
订单页面无需任何配置
export default class CompleteOrderComponent extends Component {
render() {
return (
<View style={[CommStyle.container, Component.tabBar]}>
<Text>已完成订单</Text>
</View>
);
}
}
注意:
1.导航条嵌套呈现多个导航器出现的问题:
you should only render one navigation eplicitly in you app,and other navigators should be rendered by including them in that navigator.
解决方案:
https://reactnavigation.org/docs/4.x/common-mistakes/#explicitly-rendering-more-than-one-navigator