React Native 带你一步一步实现TabNavitator(续)

本文详细介绍如何使用 React Native 构建自定义 TabNavigator 组件,包括 TabBar 和 Tab 的设计与实现,以及完整的测试代码。

React Native 带你一步一步实现TabNavitator前面我们已经大体实现了TabNavitator,下面我们接着前面的内容继续往下走哈,我们上一节写到了TabNavitator的render方法了:

 render() {
        //获取相应的props内容
        let{style,children,sceneStyle,...props}=this.props;
        //遍历所有的children
        //需要显示的页面跟显示过的页面
        let scenes=[];
        React.Children.forEach(children,(child,index)=>{
            if(child===null){
                return;
            }
            //根据子view获取唯一key
            let key=this._getSceneKey(child,index);
            let {renderedSceneKeys}=this.state;
            //判断该view是不是将要显示的view或者是不是显示过的view
            if(!renderedSceneKeys.has(key)){
                return;
            }
            //当前view为选中状态就设置其样式为sceneContainer
            let scene=null;
            if (child.props.selected) {
                scene = (
                    <View {...child.props} style={styles.sceneContainer} pointerEvents={'auto'} removeClippedSubviews={false}>
                        {child}
                    </View>
                )
            } else {//当前view为未选中状态就设置其样式为hiddenSceneContainer
                scene = (
                    <View {...child.props}style={styles.hiddenSceneContainer} pointerEvents={'none'} removeClippedSubviews={false}>
                        {child}
                    </View>
                )
            }
            if(scene!==null)scenes.push(scene);
        });

        //选出当前需要显示的view
        let currScene = null;
        scenes.forEach((page, index)=> {
            if (page.props.selected) {
                currScene = page;
                return;
            }
        });
        //render
        return (
            <View
                style={styles.container}
            >
                {currScene}
                //render我们的tabbarview
            </View>
        );
    }

我们就只差实现我们的tabbarview了,于是我们创建一个view叫TabBar:

/**
 * @author YASIN
 * @version [PABank V01,17/5/17]
 * @date 17/5/17
 * @description TabBar
 */
import React,{Component}from 'react';
import {
    View,
    Animated,
    Platform,
    StyleSheet,
}from 'react-native';
import Layout from './Layout';
export default class TabBar extends Component{
    render(){
        return(
            <Animated.View
                {...this.props}
                style={[styles.container,this.props.style]}
            >
                {this.props.children}
            </Animated.View>
        );
    }
}
const styles=StyleSheet.create({
    container:{
        position:'absolute',
        bottom: 0,
        left: 0,
        right: 0,
        flexDirection: 'row',
        justifyContent:'space-around',
        height: 49, //跟container的paddingBottom: 49对应
        backgroundColor: '#f8f8f8',
        alignItems:'center'
    }
});

没啥好说的,因为我们在写containerview的时候,当渲染当前view的时候给了一个paddingbottom:


   sceneContainer: {
        position: 'absolute',
        top: 0,
        left: 0,
        bottom: 0,
        right: 0,
        paddingBottom: 49,
        backgroundColor: 'gray'
    },

因为我们的TabBar是需要放在container的最下方的位置。

好了,创建好了TabBar后,我们就可以引入了:

         }
        });
        //render
        return (
            <View
                style={styles.container}
            >
                {currScene}
                <TabBar>
                    {/*渲染每一个Tab*/}
                </TabBar>
            </View>
        );
    }

然后我们对应每一个Tab创建一个view叫Tab:

/**
 * @author YASIN
 * @version [PABank V01,17/5/17]
 * @date 17/5/17
 * @description Tab
 */
import React,{Component,PropTypes}from 'react';
import {
    View,
    StyleSheet,
    Text,
    TouchableOpacity,
    Image
}from 'react-native';
export default class Tab extends Component{
    static propTypes={
        ...View.propTypes.style,
        renderSelectedIcon: PropTypes.func, //选中时渲染的icon
        renderIcon: PropTypes.func, //未选中时渲染的icon
        titleStyle: Text.propTypes.style, //title的style
        titleSelectedStyle: Text.propTypes.style, //title选中时的style
        title: PropTypes.string, //title
        onPress: PropTypes.func, //点击每个tab的时候
        selected: PropTypes.bool //是否选中
    }
    render(){
        let self=this;
        return(
            <TouchableOpacity
                onPress={this.props.onPress}
                activeOpacity={0.7}
            >
                <View style={[styles.container,this.props.style]}>
                    {function(){
                        let image=null;
                        if(!!self.props.selected){
                            image=self.props.renderSelectedIcon();
                        }else{
                            image=self.props.renderIcon();
                        }
                        return image;
                    }()}
                    <Text style={[this.props.selected?this.props.titleSelectedStyle:this.props.titleStyle,styles.title]}>{this.props.title}</Text>
                </View>
            </TouchableOpacity>
        );
    }
}
const styles=StyleSheet.create({
    container:{
        flexDirection:'column',
        alignItems:'center'
    },
    title:{
        fontSize:12,
        marginTop: 5
    }
});

然后我们在TabNavitator的render中修改代码:

render() {
        //获取相应的props内容
        let{style,children,sceneStyle,...props}=this.props;
        //遍历所有的children
        //需要显示的页面跟显示过的页面
        let scenes=[];
        React.Children.forEach(children,(child,index)=>{
            if(child===null){
                return;
            }
            //根据子view获取唯一key
            let key=this._getSceneKey(child,index);
            let {renderedSceneKeys}=this.state;
            //判断该view是不是将要显示的view或者是不是显示过的view
            if(!renderedSceneKeys.has(key)){
                return;
            }
            //当前view为选中状态就设置其样式为sceneContainer
            let scene=null;
            if (child.props.selected) {
                scene = (
                    <View {...child.props} style={styles.sceneContainer} pointerEvents={'auto'} removeClippedSubviews={false}>
                        {child}
                    </View>
                )
            } else {//当前view为未选中状态就设置其样式为hiddenSceneContainer
                scene = (
                    <View {...child.props}style={styles.hiddenSceneContainer} pointerEvents={'none'} removeClippedSubviews={false}>
                        {child}
                    </View>
                )
            }
            if(scene!==null)scenes.push(scene);
        });

        //选出当前需要显示的view
        let currScene = null;
        scenes.forEach((page, index)=> {
            if (page.props.selected) {
                currScene = page;
                return;
            }
        });
        //render
        return (
            <View
                style={styles.container}
            >
                {currScene}
                <TabBar>
                    {/*渲染每一个Tab*/}
                    {React.Children.map(children,this._renderTab)}
                </TabBar>
            </View>
        );
    }
    _renderTab(item,index){
        return(
            <Tab
                key={index}
                renderSelectedIcon={item.props.renderSelectedIcon}
                renderIcon={item.props.renderIcon}
                titleStyle={item.props.titleStyle}
                titleSelectedStyle={item.props.selectedTitleStyle}
                title={item.props.title}
                onPress={item.props.onPress}
                selected={item.props.selected}
            ></Tab>
        );
    }

测试代码:

/**
 * @author YASIN
 * @version [PABank V01,17/5/17]
 * @date 17/5/17
 * @description TestComponent
 */

import React,{Component}from 'react';
import {
    View,
    Text,
    StyleSheet,
    Image
}from 'react-native';
import TabNavitator from './MyTabNavitator';
import * as ScreenUtils from '../../Util/ScreenUtil';
export default class TestComponent extends Component{
    // 构造
      constructor(props) {
        super(props);
        // 初始状态
        this.state = {
            selected: '商家'
        };
      }
    render(){
        let self=this;
        return(
            <TabNavitator>
                <TabNavitator.Item
                    selected={self.state.selected==='我的'}
                    title='我的'
                    onPress={self._onItemPress.bind(self,'我的')}
                    renderIcon={() => <Image style={styles.iconStyle} source={{uri:'icon_tabbar_homepage'}} />}
                    renderSelectedIcon={() => <Image style={styles.iconStyle} source={{uri:'icon_tabbar_homepage_selected'}} />}
                    titleStyle={styles.titleStyle}
                    selectedTitleStyle={styles.selectedTitleStyle}
                >
                    <View style={{flex:1,justifyContent:'center',alignItems:'center'}}><Text style={styles.text}>我的</Text></View>
                </TabNavitator.Item>
                <TabNavitator.Item
                    selected={self.state.selected==='购物'}
                    title='购物'
                    onPress={self._onItemPress.bind(self,'购物')}
                    renderIcon={() => <Image style={styles.iconStyle} source={{uri:'icon_tabbar_homepage'}} />}
                    renderSelectedIcon={() => <Image style={styles.iconStyle} source={{uri:'icon_tabbar_homepage_selected'}} />}
                    titleStyle={styles.titleStyle}
                    selectedTitleStyle={styles.selectedTitleStyle}
                >
                    <View style={{flex:1,justifyContent:'center',alignItems:'center'}}><Text style={styles.text}>购物</Text></View>
                </TabNavitator.Item>
                <TabNavitator.Item
                    selected={self.state.selected==='商家'}
                    title='商家'
                    onPress={self._onItemPress.bind(self,'商家')}
                    renderIcon={() => <Image style={styles.iconStyle} source={{uri:'icon_tabbar_homepage'}} />}
                    renderSelectedIcon={() => <Image style={styles.iconStyle} source={{uri:'icon_tabbar_homepage_selected'}} />}
                    titleStyle={styles.titleStyle}
                    selectedTitleStyle={styles.selectedTitleStyle}
                >
                    <View style={{flex:1,justifyContent:'center',alignItems:'center'}}><Text style={styles.text}>商家</Text></View>
                </TabNavitator.Item>
            </TabNavitator>
        );
    };
    _onItemPress(title){
        this.setState({
            selected: title
        });
    }
}
const styles=StyleSheet.create({
    text:{
        color: 'red'
    },
    iconStyle: {
        width: ScreenUtils.scaleSize(40),
        height: ScreenUtils.scaleSize(40),
    },
    selectedTitleStyle: {
        color: 'orange'
    },
    titleStyle: {
        fontSize: ScreenUtils.setSpText(10),
        color: '#333333'
    }
});

好啦~~最后测试就可以看到TabNavitator的效果啦!!!

这里写图片描述

这节比较快哈~ 因为都没啥可讲的,哈哈~~一起学习一起进步。欢迎入群~~~

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值