当前位置:首页 > 芯闻号 > 充电吧
[导读]先来看下效果:这里需要用到两个第三方插件:react-native-router-flux 路由,https://github.com/aksonov/react-native-router-flux

先来看下效果:


这里需要用到两个第三方插件:

react-native-router-flux 路由,https://github.com/aksonov/react-native-router-flux

react-native-scrollable-tab-view 选项卡,https://github.com/skv-headless/react-native-scrollable-tab-view

prop-types 类型检测库

阅读官方文档,安装这三个插件

$ npm install react-native-router-flux --save
$ npm install react-native-scrollable-tab-view --save
$ npm install prop-types --save

在App.js中引入插件

import { Router, Scene } from 'react-native-router-flux';
import ScrollableTabView from 'react-native-scrollable-tab-view';

在工作目录下创建components文件夹,并添加customTabBar.js文件作为tab栏,如下

import React, {Component} from 'react';
import {
    Platform,
    StyleSheet,
    StatusBar,
    View,
    TouchableOpacity,
    Image,
    Text,
} from 'react-native';
//第三方插件
import PropTypes from 'prop-types';
//自定义组件
import Common from './common'; //公共类

const tabIcons = [
    require('../resources/images/tabs/home_v.png'),
    require('../resources/images/tabs/home_x.png'),
    require('../resources/images/tabs/headset_v.png'),
    require('../resources/images/tabs/headset_x.png'),
    require('../resources/images/tabs/bought_v.png'),
    require('../resources/images/tabs/bought_x.png'),
    require('../resources/images/tabs/mine_v.png'),
    require('../resources/images/tabs/mine_x.png')
];

export default class CustomTabBar extends Component {
    constructor(props) {
        super(props);
    }

    static setAnimationValue({value}) {
        console.log(value);
    }

    componentDidMount() {
        // Animated.Value监听范围 [0, tab数量-1]
        this.props.scrollValue.addListener(CustomTabBar.setAnimationValue);
    }

    renderTabOption(tab, i) {
        let color = this.props.activeTab === i ? "#1296db" : "#707070"; // 判断i是否是当前选中的tab,设置不同的颜色
        let tabName = this.props.tabNames[i];
        return (this.props.goToPage(i)} style={[styles.tab]} key={'tab' + i}>{tabName});
    }

    renderTabs() {
        if (true !== this.props.placeMiddle || 0 !== this.props.tabs.length%2) {
            return this.props.tabs.map((tab, i) => this.renderTabOption(tab, i));
        } else  {
            let tabs = [];
            for (let i = 0; i < this.props.tabs.length; i++) {
                let tab = this.props.tabs[i];
                if (i === parseInt(this.props.tabs.length/2)) {
                    let middle = ();
                    tabs.push(middle);
                }
                tabs.push(this.renderTabOption(tab, i));
            }
            return tabs;
        }
    }

    render() {
        let tabBarHeight = Platform.select({
            ios: Common.isIphoneX ? 68 : 49,
            android: 49,
        });
        return ({this.renderTabs()});
    }
}

CustomTabBar.propTypes = {
    goToPage: PropTypes.func, // 跳转到对应tab的方法
    activeTab: PropTypes.number, // 当前被选中的tab下标
    tabs: PropTypes.array, // 所有tabs集合
    tabNames: PropTypes.array, // 保存Tab名称
    tabIconNames: PropTypes.array, // 保存Tab图标
};

const styles = StyleSheet.create({
    tabs: {
        flexDirection: 'row',
        backgroundColor:'#ffffff',
        borderTopWidth: 0.5,
        borderTopColor: '#cdcdcd',
    },
    tab: {
        flex: 1,
        flexDirection: 'column',
        justifyContent: 'center',
        alignItems: 'center',
    },
    tabBox: {
        flexDirection: 'column',
        justifyContent: 'center',
        alignItems: 'center',
        width: 48,
        height: 48,
    },
    tabMiddleBox: {
        flex: 1,
        flexDirection: 'column',
        justifyContent: 'center',
        alignItems: 'center',
        width: 48,
        height: 48,
    },
    tabBoxIcon: {
        width: 22,
        height: 22,
    },
    tabBoxName: {
        fontSize: 10,
        marginTop: 3,
    },
});

这里用到了一个公共类common.js

import {
    Dimensions,
    PixelRatio,
    Platform
} from 'react-native';


export let screenWidth = Dimensions.get('window').width;
export let screenHeight = Dimensions.get('window').height;
export let fontScale = PixelRatio.getFontScale();
export let pixelRatio = PixelRatio.get();


//像素密度
export const DEFAULT_DENSITY = 2;
//px转换成dp
//以iphone6为基准,如果以其他尺寸为基准的话,请修改下面的750和1334为对应尺寸即可.
const width2x = 750 / DEFAULT_DENSITY;
//px转换成dp
const height2x = 1334 / DEFAULT_DENSITY;
// iPhoneX
const X_WIDTH = 375;
const X_HEIGHT = 812;


/**
 * 设置字体的size(单位px)
 * @param size 传入设计稿上的px
 * @returns {Number} 返回实际sp
 */
export function autoFontSize(size) {
    let scaleWidth = screenWidth / width2x;
    let scaleHeight = screenHeight / height2x;
    let scale = Math.min(scaleWidth, scaleHeight);
    size = Math.round((size * scale + 0.5));
    return size / DEFAULT_DENSITY;
}


/**
 * 屏幕适配,缩放size
 * @param size
 * @returns {Number}
 */
export function autoScaleSize(size) {
    let scaleWidth = screenWidth / width2x;
    let scaleHeight = screenHeight / height2x;
    let scale = Math.min(scaleWidth, scaleHeight);
    size = Math.round((size * scale + 0.5));
    return size / DEFAULT_DENSITY;
}


/**
 * 判断是否为iphoneX
 * @returns {boolean}
 */
export function isIphoneX() {
    return (
        Platform.OS === 'ios' &&
        ((screenHeight === X_HEIGHT && screenWidth === X_WIDTH) ||
        (screenHeight === X_WIDTH && screenWidth === X_HEIGHT))
    )
}


Date.prototype.format=function(fmt) {
    let o = {
        "M+" : this.getMonth()+1, //月份
        "d+" : this.getDate(), //日
        "h+" : this.getHours()%12 === 0 ? 12 : this.getHours()%12, //小时
        "H+" : this.getHours(), //小时
        "m+" : this.getMinutes(), //分
        "s+" : this.getSeconds(), //秒
        "q+" : Math.floor((this.getMonth()+3)/3), //季度
        "S" : this.getMilliseconds() //毫秒
    };
    let weekday = {
        "0" : "/u65e5",
        "1" : "/u4e00",
        "2" : "/u4e8c",
        "3" : "/u4e09",
        "4" : "/u56db",
        "5" : "/u4e94",
        "6" : "/u516d"
    };
    if(/(y+)/.test(fmt)){
        fmt=fmt.replace(RegExp.$1, (this.getFullYear()+"").substr(4 - RegExp.$1.length));
    }
    if(/(E+)/.test(fmt)){
        fmt=fmt.replace(RegExp.$1, ((RegExp.$1.length>1) ? (RegExp.$1.length>2 ? "/u661f/u671f" : "/u5468") : "")+weekday[this.getDay()+""]);
    }
    for(let k in o){
        if(new RegExp("("+ k +")").test(fmt)){
            fmt = fmt.replace(RegExp.$1, (RegExp.$1.length===1) ? (o[k]) : (("00"+ o[k]).substr((""+ o[k]).length)));
        }
    }
    return fmt;
};


export default class Common {
    static SCREEN_WIDTH = screenWidth;
    static SCREEN_HEIGHT = screenHeight;
    static PIXEL_RATIO = pixelRatio;
    static DEFAULT_DENSITY = DEFAULT_DENSITY;


    //是否为iphoneX
    static isIphoneX = isIphoneX();


    //字体自适应大小
    static autoFontSize(size) {
        return autoFontSize(size);
    }


    //尺寸自适应大小
    static autoScaleSize(size) {
        return autoScaleSize(size);
    }


    //获取指定格式时间字符串
    static getDateFormat(date, format = false) {
        if (false !== format) {
            format = "yyyy-MM-dd HH:mm:ss";
        }
        return date.format(format);
    }
}

然后在App.js内渲染路由和tab,注意在路由外层要包一个View,以便后面我们使用全局的toast和loading,同时tab作为路由中的一个页整体呈现。

//自定义组件
import CustomTabBar from './components/customTabBar'; //自定义选项卡
//选项卡Tab页
import HomeTabScreen from './views/home'; //首页
import HeadsetTabScreen from './views/headset'; //试听
import BoughtTabScreen from './views/bought'; //已购
import MineTabScreen from './views/mine'; //我的
//页面
import SignInOrUpScreen from './views/signIns/signInOrUp'; //免注册登录
import SignInScreen from './views/signIns/signIn'; //登录

// const instructions = Platform.select({
//   ios: 'Press Cmd+R to reload,n' +
//     'Cmd+D or shake for dev menu',
//   android: 'Double tap R on your keyboard to reload,n' +
//     'Shake or press menu button for dev menu',
// });

export class Tabs extends Component {
    constructor(props) {
        super(props);
    }

    componentWillMount() {
        // Disable back button by just returning true instead of Action.pop()
        BackHandler.addEventListener('hardwareBackPress', () => {return true});
    }

    render() {
        let tabNames = ['首页', '试听', '已购', '我的'];
        return (}
                tabBarPosition='bottom'
            >);
    }
}

export default class App extends Component {
    render() {
        return ({/*首页(tab)*/}{/*登录*/});
    }
}

const styles = StyleSheet.create({
    router: {
        backgroundColor: '#e6e6e6',
    },
    root: {
        backgroundColor: '#e6e6e6',
    },
    title: {
        color: '#ffffff',
    },
});

这样就把路由和tab集成到一起了,关于路由的使用这里有个详解《react-native-router-flux使用技巧(API篇)》,我这里就说一些简单的跳转。

Actions.pop()

返回上一页。

Actions.key()

不带参跳转到键为key的页,Actions.key()中的key即为Scene的key属性值,如代码中的home和signInOrUp。


Actions.key(param)

带参数跳转到键为key的页,Actions.key()中的key即为Scene的key属性值,如代码中的home和signInOrUp。

参数可以通过属性获取,如this.props.param。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

May 9, 2024 ---- 据TrendForce集邦咨询研究显示,2023年全球前十大IC设计业者营收合计约1,677亿美元,年增长12%,关键在于NVIDIA(英伟达)带动整体产业向上,其营收年成长幅度高达10...

关键字: NVIDIA IC设计 AI

May 8, 2024 ---- 苹果5月新品发布会推出主打AMOLED屏幕的平板产品,新款Pro版本的AMOLED屏幕采用双层串联结构,目的在于改善AMOLED屏幕长期存在的烧屏及寿命问题,而无需背光模组的优势也迎来史...

关键字: Apple iPad Pro 显示器

尼得科精密部件基于自创立以来在相机产业培育起来的“精密”制造技术,利用精致且高水平的小型振动电机技术,从零开始重新设计与薄型最为适合的磁路,最终实现了厚度仅为1.4mm的*全球超薄型线性致动器“TapSense”。由此,...

关键字: 线性振动致动器 电机

5月8日,海信旗下年轻科技潮牌Vidda在北京发布新品AI电视和三色激光智能投影。作为2024欧洲杯官方指定智能投影。Vidda副总经理郭琛介绍,2023年,Vidda电视在国内线上市场的量占有率近10%,牢牢占据行业前...

关键字: 人工智能 三色激光 投影

现有股东Philip Fayer将转出其绝大部分现有股权,现有股东Novacap和CDPQ将转出其大部分现有股权 主要亮点: 全球领先的支付公司Nuvei与金融科技私募股权投资领域的重要企业Advent通过全现...

关键字: NOVA IP INTERNATIONAL CD

上海2024年5月8日 /美通社/ -- 近年来,随着国家医疗政策改革的红利释放以及企业在研发投入方面不断加码,中国医疗器械产业步入黄金发展期,国内医疗器械企业攻坚关键核心技术,在高端领域不断突破,"出海&qu...

关键字: 显微镜 光学 高精度 质量检测

共创包容性数字未来 新加坡2024年5月8日 /美通社/ -- 5月29日至31日,亚洲旗舰科技平台新加坡亚洲科技大会(Asia Tech x Singapore,简称AT...

关键字: 新加坡 ATX AN TE

北京2024年5月8日 /美通社/ -- 4月28日至29日,以"算力网络点亮AI新时代"为主题的2024中国移动算力网络大会在苏州隆重举行。此次大会旨在构建一个开放协同、融合创新的平台,以推动算网技...

关键字: 网络 中国移动 AI 数字化

深圳2024年5月6日 /美通社/ -- 从4月23日的一场大会开始,到24-26日的IOTE会展节,我们共同见证了物联网领域的最新技术、产品和解决方案的集中展示,感受到了AIoT释放数字经济潜力的巨大能量。今天以展商满...

关键字: IoT 物联网 TE AIOT
关闭
关闭