React Native -- React-Navigation

452 阅读3分钟

      TabBar控件在移动端App中使用的频率比较高,故今天来探讨一下React Native中的实现方式。查阅资料发现TabNavigator方法已经被废弃,需要引入文件react-navigation文件,下载对应资源的方法:

npm install --save react-navigation

   导入该资源文件后,运行Xcode会报错,需要执行npm install操作,有时候执行初始化操作后会出现以下错误:

                            Unexpected end of JSON input while parsing near

    解决办法:

                            运行npm cache clean --force 完美解决

        OK。配置结束后,根据我之前iOS开发经验,需要用TabBarController来管理多个由NavigationController管理的一系列ViewController。那么问题来了,切换场景得时候可能有隐藏TabBar的需求,按照刚才所说的方法,我需要set一个值来控制tabbar的heightoverflow,又由于component的生命周期函数中没有类似于iOS中-(void)viewWillAppear;的方法,所以没有很好的方法把隐藏的tabbar再显示出来。

        So,只能换一种思路,把管理一系列视图的Tab交由一个Navigator管理,虽然这样违背了iOS开发的普通思路,但是就目前在RN项目中,没有发现太大的问题(有一个问题是只有一级页面显示TabBar,所有二级页面全部不显示,不过就国内大多数应用设计风格来看,这个问题也不算是问题)。但是同样会出现问题,Tab管理的页面导航栏标题不更新。


        查阅资料,发现好多小伙伴都用自定义的导航栏来解决这一办法,但是同样会存在一个适配得问题,比如iPhoneX的导航栏高度就是一个特例,安卓机型导航栏的高度应该也是很繁琐。(如果你有更好得办法,求告知)

具体实现如下:

import {createBottomTabNavigator, createStackNavigator} from 'react-navigation';
import Home from './Home';
import Order from './Order';
import Mine from './Mine';
import HomeDetails from './HomeDetails';

export default class NCITab extends Component {
    render() {
        return (
            <NCINavigation/>
        );
    }
}

const NCIAppTabBar = createBottomTabNavigator({
    /*首页*/
    Home: {
        screen:Home,
        navigationOptions: {
            tabBarLabel:'首页',
            tabBarIcon:({tintColor})=>(
                <Image source={{uri:'icon_car_active'}} style={[styles.tabIcon, {tintColor:tintColor}]} />
            ),
        },
    },

    /*订单*/
    Order: {
        screen:Order,
        navigationOptions:{
            tabBarLabel:'订单',
            tabBarIcon:({tintColor})=>(
                <Image source={{uri:'icon_bill'}} style={[styles.tabIcon, {tintColor:tintColor}]} />
            ),
        },
    },

    /*我的*/
    Mine: {
        screen:Mine,
        navigationOptions:{
            tabBarLabel:'我的',
            tabBarIcon:({tintColor})=>(
                <Image source={{uri:'icon_user'}} style={[styles.tabIcon, {tintColor:tintColor}]} />
            ),
        },
    }
}, {
    // 设置TabNavigator的位置
    tabBarPosition:'bottom',
    // 是否在更改标签时显示动画
    animationEnabled:true,

    // 进入App的首页面
    // initialRouteName:'Home',

    // 是否允许在标签之间进行滑动
    swipeEnabled: true,
    // 按 back 键是否跳转到第一个Tab(首页), none 为不跳转
    backBehavior: "none",

    tabBarOptions:{
        // 是否显示图标,默认关闭
        showIcon:true,
        // label和icon的前景色 活跃状态下(选中)
        activeTintColor: '#187ae6',
        // label和icon的前景色 活跃状态下(未选中)
        inactiveTintColor: '#232323',

        // TabNavigator 的背景颜色
        style:{
            backgroundColor:'white',
            height:49,
        },

        // 标签指示器的样式对象(选项卡底部的行)。安卓底部会多出一条线,可以将height设置为0来暂时解决这个问题
        indicatorStyle: {
            height: 0,
        },

        // 文字样式
        labelStyle: {
            fontSize:13,
        },

        // 图标的样式
        iconStyle: {
            marginBottom:5,
        }
    },
    mode:'card',
});

const NCINavigation = createStackNavigator({
    HomeVC:{
        screen:NCIAppTabBar,
        navigationOptions:{
            header:null,
        }
    },

    HomeDetails:{
        screen:HomeDetails,
    }
});

自定义导航栏实现:

const NAVBAR_HEIGHT_ANDROID=50;
const STATUS_BAR_HEIGHT=20;
const STATUS_BAR_X_HEIGHT=44;
const TITLE_VIEW_HEIGHT = 44;

// iPhoneX
const X_WIDTH = 375;
const X_HEIGHT = 812;


// screen
const SCREEN_WIDTH = Dimensions.get('window').width;
const SCREEN_HEIGHT = Dimensions.get('window').height;

export function isIphoneX() {
    return (
        Platform.OS === 'ios' &&
        ((SCREEN_HEIGHT === X_HEIGHT && SCREEN_WIDTH === X_WIDTH) ||
            (SCREEN_HEIGHT === X_WIDTH && SCREEN_WIDTH === X_HEIGHT))
    )
}

export function ifIphoneX (iphoneXStyle, regularStyle) {
    if (isIphoneX()) {
        return iphoneXStyle;
    } else {
        return regularStyle
    }
}


export default class HeaderNav extends Component {
    render() {
        return (
            <View style={styles.navView}>
                <View style={styles.statusView}></View>
                <View style={styles.titleView}>
                    <Text style={styles.titleText}>{this.props.titleName}</Text>
                </View>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    //  主要就是计算这个地方高度
    navView: {
        flex:1,
        height:Platform.OS === 'ios' ? ifIphoneX(STATUS_BAR_X_HEIGHT, STATUS_BAR_HEIGHT) + TITLE_VIEW_HEIGHT : NAVBAR_HEIGHT_ANDROID,
    },

    statusView: {
        height:Platform.OS === 'ios' ? ifIphoneX(STATUS_BAR_X_HEIGHT, STATUS_BAR_HEIGHT) : 20,
    },

    titleView: {
        height:44,
        justifyContent:'center',
        alignItems:'center',
    },

    titleText: {
        fontSize:17,
        fontWeight:'700',
        textAlign:'center',
        color:'rgba(0, 0, 0, 0.9)',
    }
});

只能以这种方式来解决了,有好的指导意见求指教。


实现效果如下: