RN0.57新版本实现TabNavigator自定义中间凸出Tab

第一次写技术博客_(:°з」∠)_

第一次写技术博客,以往都是伸手党,这次难得自己想写个博客,最近才从游戏转行做RN,所以很多东西都不懂,这次的博客中代码也是很多借鉴了其他大佬的博客内容。项目中要实现一个Tabber中凸出一个按钮的效果,类似闲鱼App中“+”按钮的样式。参考了很多大佬的写法,我同事找到最方便的是tabBarButtonComponent这个东东,有兴趣的可以去看一下,我这里介绍的是大佬们重新渲染TabBar的方式。

代码部分

// An highlighted block
import React, { Component } from 'react';
import {
    Text,
    View,
    TouchableOpacity,
} from 'react-native';

export default class Tab extends Component {

    renderItem = (route, index) => {
        const {
            navigation,
        } = this.props;

        const focused = index === navigation.state.index;
        const color = focused ? this.props.activeTintColor : this.props.inactiveTintColor;
        let TabScene = {
            focused: focused,
            route: route,
            tintColor: color
        };

        if (index === 1) {
            return (<View
                key={route.key}
                style={[styles.tabItem, { backgroundColor: 'transparent' }]}>
            </View>
            );
        }

        return (
            <TouchableOpacity
                key={route.key}
                style={styles.tabItem}
                onPress={() => this.props.jumpTo(route.key)}
            >
                <View
                    style={styles.tabItem}>
                    {this.props.renderIcon(TabScene)}
                    <Text style={{ ...styles.tabText, marginTop: SCALE(10), color }}>{this.props.getLabelText(TabScene)}</Text>
                </View>
            </TouchableOpacity>
        );
    };
    render() {
        const { navigation, } = this.props;
        const { routes, } = navigation.state;
        const focused = 1 === navigation.state.index;
        const color = focused ? this.props.activeTintColor : this.props.inactiveTintColor;
        let TabScene = {
            focused: focused,
            route: routes[1],
            tintColor: color
        };
        return (<View style={{ width: WIDTH }}>
            <View style={styles.tab}>
                {routes && routes.map((route, index) => this.renderItem(route, index))}
            </View>
            {/*设置中间按钮凸出样式  使用绝对定位*/}
            <TouchableOpacity
                key={"centerView"}

                style={[styles.tabItem, { position: 'absolute', bottom: 0, left: (WIDTH - SCALE(100)) / 2, right: WIDTH - SCALE(100), height: SCALE(120) }]}
                onPress={() => this.props.jumpTo(TabScene.route.key)}>
                <View
                    style={styles.tabItem}>
                    {this.props.renderIcon(TabScene)}
                    <Text style={{ ...styles.tabText, marginTop: SCALE(10), color }}>{this.props.getLabelText(TabScene)}</Text>
                </View>
            </TouchableOpacity>
        </View>);
    }
}
const styles = {
    tab: {
        width: WIDTH,
        backgroundColor: 'transparent',
        flexDirection: 'row',
        justifyContent: 'space-around',
        alignItems: 'flex-end'
    },
    tabItem: {
        height: SCALE(80),
        width: SCALE(100),
        alignItems: 'center',
        justifyContent: 'center'
    },
    tabText: {
        marginTop: SCALE(13),
        fontSize: FONT(10),
        color: '#7b7b7b'
    },
    tabTextChoose: {
        color: '#f3474b'
    },
    tabImage: {
        width: SCALE(42),
        height: SCALE(42),
    },
};

ps:我测试的项目Tabbar按钮是三个,所以用的index用的1,可以根据自己项目更改,我想你代码要是看了也知道改哪里的1。。ε٩(๑> ₃ <)۶з

关于SCALE,WIDTH,FONT没有定义的问题,是另外一个代码写的,具体如下

import { Dimensions, PixelRatio, Platform } from 'react-native';
export const deviceWidth = Dimensions.get('window').width;      //设备的宽度
export const deviceHeight = Dimensions.get('window').height;    //设备的高度
let fontScale = PixelRatio.getFontScale();                      //返回字体大小缩放比例
let pixelRatio = PixelRatio.get();      //当前设备的像素密度
const defaultPixel = 2;
//iphone6的像素密度
//px转换成dp
const defaultW = Platform.OS === 'ios' ? 750 : 720;
const defaultH = Platform.OS === 'ios' ? 1334 : 1280;
const w2 = defaultW / defaultPixel;
const h2 = defaultH / defaultPixel;
const scale = Math.min(deviceHeight / h2, deviceWidth / w2);   //获取缩放比例
//noinspection JSAnnotator
/**
 * 设置text为sp
 * @param size sp
 * return number dp
 */
export function setSpText(size: number) {
    // size = size/pixelRatio;
    // size = Math.round((size * scale + 0.5) * pixelRatio / fontScale);
    return size;
}

//noinspection JSAnnotator
export function scaleSize(size: number) {
    size = Math.round(size * scale + 0.5);
    return size / defaultPixel;
}

global.FONT = setSpText;

global.SCALE = scaleSize;

global.WIDTH = deviceWidth;

global.HEIGHT = deviceHeight;

PS:上面代码如何引用只要再你的index.js文件中import

import {AppRegistry} from 'react-native';
import './app/Util/Global';//这个就是上面代码所在的文件
import test from './app/00_hello_world/App';
import {name as appName} from './app.json';
AppRegistry.registerComponent(appName, () => test);

具体使用如下

const BottomNavigator = createBottomTabNavigator(
	{
		home_dynamic: {
			screen: PropsTest,
			navigationOptions: {
				title:'动态',
				tabBarLabel: "动态",
				tabBarIcon: ({ focused }) => (
					<Image
						source={focused ? icon_dynamic_f : icon_dynamic_n}
						style={{ width: 74 / 3, height: 65 / 3 }}
					/>
				),
			},
		},
		home_message: {
			screen: CSSTest,
			navigationOptions: {
				title:'消息',
				tabBarLabel: "消息",
				tabBarIcon: ({ focused }) => (
					<Image
						source={focused ? icon_message_f : icon_message_n}
						style={{ width: 74 / 3, height: 74 / 3 }}
					/>
				),
			},
		},
		home_world: {
			screen: InputText,
			navigationOptions: {
				title:'世界',
				tabBarLabel: "世界",
				tabBarIcon: ({ focused }) => (
					<Image
						source={focused ? icon_world_f : icon_world_n}
						style={{ width: 84 / 3, height: 66 / 3 }}
					/>
				),
			},
		},
	},
	{
		initialRouteName: "home_dynamic",
		tabBarPosition: "bottom",
		animationEnabled: true,
		swipeEnabled: false,
		lazy: true,
		backBehavior: "none",
		tabBarComponent: props => <Tab {...props} />,//用作渲染tab bar的组件
		tabBarOptions: {
			upperCaseLabel: false,
			showIcon: true,
			showLabel: true,
			activeTintColor: "#00AAFFFF",
			inactiveTintColor: "#838383FF",
			style: {
				// height: 55,
				backgroundColor: "#FFFFFFFF",
				borderTopWidth: 0.5,
				borderTopColor: "#00000032",
			},
		},
	},
);

本人RN小白,上面代码我这里是测试没问题了,如果大佬有更好的方式或者上面代码有问题,希望能够指出,谢谢了。d(`・∀・)b

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值