React Native—使用ScrollableTabView实现APP底部导航栏(带消息圆点)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_33721382/article/details/83927520

icon_selected color:#d81e06

icon_unselected color:#515151

一、前言

这段时间在公司开始搞React Native开发,要对APP的主页底部导航栏进行替换,寻找了多种方法,最后使用react-native-scrollable-tab-view库的ScrollableTabView实现了想要的功能(控制Tab页面的显示和隐藏、带消息圆点指示器)。

组件的地址:https://www.npmjs.com/package/react-native-scrollable-tab-view

二、效果图

 

消息圆点位置、样式可以自行设置参数来调整。

三、自定义的tabBar组件(关键代码)

实现这个导航栏的关键点在于自定义的tabBar组件。这个组件里面实现选中页面和非选中页面的图标切换和消息圆点的渲染,很多控制逻辑都封装在了里面。以下是自定义组件的代码(各位可根据需要自行改造):

import React from 'react';

import PropTypes from 'prop-types';

import {

    View,

    Text,

    Button,

    Image,

    StyleSheet,

    TouchableOpacity,

    ViewPropTypes

} from 'react-native';



import {

    Badge

} from 'teaset';



/**

 * 2018-11-10

 * chenlw

 * work:自定义ScrollableTabViewPage的TabBar

 */

export default class MyTabBar extends React.Component {



    propTypes = {

        goToPage: PropTypes.func, // 跳转到对应tab的方法

        activeTab: PropTypes.number, // 当前被选中的tab下标

        tabs: PropTypes.array, // 所有tabs集合

        goToPage: PropTypes.func,

        backgroundColor: PropTypes.string,

        activeTextColor: PropTypes.string,

        inactiveTextColor: PropTypes.string,

        textStyle: Text.propTypes.style,

        tabStyle: ViewPropTypes.style,

        renderTab: PropTypes.func,

        underlineStyle: ViewPropTypes.style,

    }



    //未选中的图标

    tabUnselectedIcons = [

        require('./icons/icon_message_unselected.png'),

        require('./icons/icon_my_unselected.png'),

    ];

    //选中的图标

    tabSelectedIcons = [

        require('./icons/icon_message_selected.png'),

        require('./icons/icon_my_selected.png'),

    ];



    constructor(props) {

        super(props);

    }



    static defaultProps = {

        activeTextColor: 'navy',

        inactiveTextColor: 'black',

        backgroundColor: null,

    };



    /**

     * 是否显示该Tab

     * @param {*} pageIndex

     */

    isRenderTab(pageIndex) {

        let hideTabIndexSet = this.props.hideTabIndexSet;

        if (hideTabIndexSet) {

            return !hideTabIndexSet.has(pageIndex);

        }

        return true;

    }



    render() {

        return (

            <View style={[styles.tabs, { backgroundColor: this.props.backgroundColor }, this.props.style,]}>

                <View style={{ flex: 1, flexDirection: 'row' }}>

                    {this.props.tabs.map((name, pageIndex) => {

                        if (this.isRenderTab(pageIndex)) {

                            //判断是否渲染该页面

                            const isTabActive = this.props.activeTab === pageIndex;

                            return this.renderTab(name, pageIndex, isTabActive, this.props.goToPage);

                        }

                    })}

                </View>

            </View>

        );

    }



    renderTab(name, pageIndex, isTabActive, onPressHandler) {

        const { activeTextColor, inactiveTextColor, textStyle, } = this.props;

        const textColor = isTabActive ? activeTextColor : inactiveTextColor;

        const fontWeight = isTabActive ? 'bold' : 'normal';



        return (

            <View style={{ flex: 1 }}>

                <TouchableOpacity

                    style={{ flex: 1 }}

                    onPress={() => onPressHandler(pageIndex)}>

                    <View style={[styles.tab, this.props.tabStyle,]}>

                        {

                            this.renderTabBadge(name)

                        }

                        <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>

                            {

                                this.renderTabIcon(pageIndex, isTabActive)

                            }

                            <Text style={{ color: textColor }}>{name}</Text>

                        </View>



                    </View>

                </TouchableOpacity>

            </View>

        );

    }



    /**

     显示Tab的图标

     * require指令不支持变量类型

     * @param {*} pageIndex

     * @param {*} isTabActive

     */

    renderTabIcon(pageIndex, isTabActive) {

        if (isTabActive) {

            return <Image source={this.tabSelectedIcons[pageIndex]}></Image>;;

        } else {

            return <Image source={this.tabUnselectedIcons[pageIndex]}></Image>;;

        }

    }



    /**

     * 显示消息红点

     * @param {*} pageName

     */

    renderTabBadge(pageName) {

        switch (pageName) {

            case "消息":

                return <Badge style={{ position: 'absolute', right: 5, top: 5, }} count={10} />;

            case "我的":

                return <Badge style={{ position: 'absolute', right: 5, top: 5, }} count={12} />;

        }

        return null;

    }



}



const styles = StyleSheet.create({

    tab: {

        flex: 1,

        alignItems: 'center',

        justifyContent: 'center',

    },

    tabs: {

        height: 50,

        flexDirection: 'row',

        // justifyContent: 'space-around',

        borderWidth: 2,

        borderTopWidth: 0,

        borderLeftWidth: 0,

        borderRightWidth: 0,

        borderColor: '#ccc',

    },

});

 

四、控制Tab页面的显示和隐藏

实现控制Tab页面的显示和隐藏的思想:通过一个Set集合来决定页面是否隐藏,如果页面的下标存在该Set集合内则不显示,反之则显示。关键代码有两处,一处是主页的隐藏页面参数的初始化,代码如下:

constructor(props) {

        super(props);



        /**

         * 实现隐藏特定页面的功能:把要隐藏的页面下标加入hideTabIndexSet就可以实现,比如要隐藏消息页面,就hideTabIndexSet.add(0);

         * 注意:

         * (1)要将这个属性传递到自定义tabBar的props,这样自定义tabBar组件才能读取数据。

         * (2)同时要修改ScrollableTabView组件的初始化页面下标,不然显示的页面就有可能错误。

         */

        const hideTabIndexSet = new Set();

        //hideTabIndexSet.add(0);



        //初始化页面的下标

        const initialPage = 0;



        this.state = {

            activeIndex: 0,

            hideTabIndexSet: hideTabIndexSet,

            initialPage: initialPage,

        }

    }

 

扫描二维码关注公众号,回复: 5843805 查看本文章

把hideTabIndexSet传递到MyTabBar里面:

<MyTabBar hideTabIndexSet={this.state.hideTabIndexSet}></MyTabBar>

 

第二处是在MyTabBar组件里面,控制页面的隐藏,代码如下:

render() {

        return (

            <View style={[styles.tabs, { backgroundColor: this.props.backgroundColor }, this.props.style,]}>

                <View style={{ flex: 1, flexDirection: 'row' }}>

                    {this.props.tabs.map((name, pageIndex) => {

                        if (this.isRenderTab(pageIndex)) {

                            //判断是否渲染该页面

                            const isTabActive = this.props.activeTab === pageIndex;

                            return this.renderTab(name, pageIndex, isTabActive, this.props.goToPage);

                        }

                    })}

                </View>

            </View>

        );

    }

 

资源下载地址:

  1. CSDN:https://download.csdn.net/download/qq_33721382/10776196
  2. Github:https://github.com/chenliwu/MyAppNavigationDemo

如果你觉得我写的不错,就关注我吧!

猜你喜欢

转载自blog.csdn.net/qq_33721382/article/details/83927520