RN导航03—createMaterialTopTabNavigator顶部导航组件

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中的widthleft以百分比的形式设置值实现:

 

扩展

此时需求又变更了,我们需要指示器固定长度圆角居中显示在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事件。

方案二:通过自定义StackNavigation导航栏实现

 不足:无法通过左右滑动切换页面(如果并不需要实现滑动切换页面可以使用此方式)

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

 

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值