React Native 系列(九)

前言

本系列是基于React Native版本号0.44.3写的。很多的App都使用了Tab标签组件,例如QQ微信等等,就是切换不同的选项,显示不同的内容。那么这篇文章将介绍RN中的Tab标签组件。

Tab标签

什么是Tab标签?(ps:我是这样叫的),就拿微信来说吧,底部有4个选项卡,点击不同的按钮切换不同的内容。
RN中有两个组件负责实现这样的效果,它们是:

TabBarIOS

NavigatorIOS相似,看名字就知道该组件只适用于iOS,不能用于android

TabBarIOS 常用属性

barTintColor string:标签栏的背景颜色。
style:样式
tintColor string: 当前被选中的标签图标的颜色。 unselectedItemTintColor string: 当前没有被选中的标签图标的颜色。仅在iOS 10及以上版本有效
translucent bool: 一个布尔值,决定标签栏是否需要半透明化。

TabBarIOS.Item

  • 注意:TabBarIOS.Item必须包装一个View,作为点击选项卡,切换的view

TabBarIOS.Item 常用属性

badge string, number :在图标右上角显示一个红色的气泡。

icon Image.propTypes.source :给当前标签指定一个自定义的图标。如果定义了systemIcon属性, 这个属性会被忽略。 

onPress function :当此标签被选中时调用。你应该修改组件的状态来使得selected={true}。 

selected bool :这个属性决定了子视图是否可见。如果你看到一个空白的页面,很可能是没有选中任何一个标签。 

selectedIcon Image.propTypes.source :当标签被选中的时候显示的自定义图标。如果定义了systemIcon属性,这个属性会被忽略。如果定义了icon而没定义这个属性,在选中的时候图标会染上蓝色。 

systemIcon enum(‘bookmarks‘, ‘contacts‘, ‘downloads‘, ‘favorites‘, ‘featured‘, ‘history‘, ‘more‘, ‘most-recent‘, ‘most-viewed‘, ‘recents‘, ‘search‘, ‘top-rated‘) :一些预定义的系统图标。注意如果你使用了此属性,标题和自定义图标都会被覆盖为系统定义的值。 

title string :在图标下面显示的标题文字。如果定义了systemIcon属性,这个属性会被忽略

使用步骤

  1. 创建TabBar标签: 使用下面行代码,底部就会有一个条

    <TabBarIOS>
    </TabBarIOS>
  2. 添加选项卡
    <TabBarIOS.Item
            title=‘首页‘
            icon={{uri: ‘tabbar_home_select‘ , scale: 3}}
    >
        <View style={{flex: 1, justifyContent: ‘center‘, alignItems: ‘center‘, backgroundColor: ‘red‘}}>
            <Text>首页</Text>
        </View>
    </TabBarIOS.Item>
  3. 监听按钮点击,切换界面
    • 只要设置对应的tabBarItemselectedtrue,就会自动跳转到对应界面
    • 注意:tabBarItemselected属性不能写死,可以定义个flag来标记当前选中的item
    • 监听tabBarItem的点击,修改selected属性

实战演练

先看效果图:

我们在index.ios.js文件做修改,直接创建一个TabBarIOS组件:

render() {
    return (
        <TabBarIOS
            tintColor=‘orange‘
            barTintColor=‘black‘
        >
        </TabBarIOS>
    );
}

再创建三个选项卡(ps:3个选项卡创建方式类似,所以这里只贴出创建一个的代码,),icon是图片,关于图片方面的知识,本文最后做一个总结吧:

<TabBarIOS.Item
        title=‘首页‘
        icon={{uri: ‘tabbar_home_select‘ , scale: 3}}
        selected={true}
    >
        <View style={{flex: 1, justifyContent: ‘center‘, alignItems: ‘center‘, backgroundColor: ‘red‘}}>
            <Text>首页</Text>
        </View>

</TabBarIOS.Item>

监听按钮点击,然后实现界面切换,我们需要定义一个flag记录当前选中的,

constructor(props) {
    super(props);
    // 初始状态
    this.state = {
        selectIndex:0,
    };
}

TabBarIOS.Item添加点击事件:

<TabBarIOS.Item
    title=‘首页‘
    icon={{uri: ‘tabbar_home_select‘ , scale: 3}}
    onPress={()=>{
        this.setState({
            selectIndex:0
        })
    }}
    selected={0==this.state.selectIndex}
>

我们会发现,创建3个TabBarIOS.Item的代码是一样的,避免写重复代码,我们可以抽取出来:

_renderTabBarItem(title, iconName, selected, bgColor, badgeNumber){
    return (
        <TabBarIOS.Item
            title={title}
            icon={{uri: iconName, scale: 3}}
            onPress={()=>{
                this.setState({
                    selectIndex: selected
                })
            }}
            badge={badgeNumber}
            selected={this.state.selectIndex === selected}
        >
            <View style={{flex: 1, justifyContent: ‘center‘, alignItems: ‘center‘, backgroundColor: bgColor}}>
                <Text>{title}</Text>
            </View>
        </TabBarIOS.Item>
    );
}

然后我们整个创建标签Tab的代码就应该是这样:

render() {
    return (
        <TabBarIOS
            tintColor=‘orange‘
            barTintColor=‘black‘
        >
            {this._renderTabBarItem("首页", ‘tabbar_my_select‘, 0, ‘red‘, null)}
            {this._renderTabBarItem("消息", ‘tabbar_my_select‘, 1, ‘yellow‘, 2)}
            {this._renderTabBarItem("我的", ‘tabbar_my_select‘, 2, ‘cyan‘, null)}

        </TabBarIOS>
    );
}

TabNavigator

本系列上篇文章中,介绍到React Navigation组件中包含了TabNavigator。所以接下来的讲解是在引入了React Navigation的基础之上的。

常用属性

screen:和导航的功能是一样的,对应界面名称,可以在其他页面通过这个screen传值和跳转。  

navigationOptions:配置TabNavigator的一些属性
{
    title:标题,会同时设置导航条和标签栏的title
    tabBarVisible:是否隐藏标签栏。默认不隐藏(true)
    tabBarIcon:设置标签栏的图标。需要给每个都设置
    tabBarLabel:设置标签栏的title。推荐
}

tabBarPosition:设置tabbar的位置,iOS默认在底部,安卓默认在顶部。(属性值:‘top‘,‘bottom‘)  

swipeEnabled:是否允许在标签之间进行滑动  

animationEnabled:是否在更改标签时显示动画  

lazy:是否根据需要懒惰呈现标签,而不是提前,意思是在app打开的时候将底部标签栏全部加载,默认false,推荐为true  

trueinitialRouteName: 设置默认的页面组件  

backBehavior:按 back 键是否跳转到第一个Tab(首页), none 为不跳转  

tabBarOptions:配置标签栏的一些属性iOS属性  

activeTintColor:label和icon的前景色 活跃状态下  

activeBackgroundColor:label和icon的背景色 活跃状态下  

inactiveTintColor:label和icon的前景色 不活跃状态下  

inactiveBackgroundColor:label和icon的背景色 不活跃状态下  

showLabel:是否显示label,默认开启 style:tabbar的样式  

labelStyle:label的样式安卓属性  

activeTintColor:label和icon的前景色 活跃状态下  

inactiveTintColor:label和icon的前景色 不活跃状态下  

showIcon:是否显示图标,默认关闭  

showLabel:是否显示label,默认开启 style:tabbar的样式  

labelStyle:label的样式 upperCaseLabel:是否使标签大写,默认为true  

pressColor:material涟漪效果的颜色(安卓版本需要大于5.0)  

pressOpacity:按压标签的透明度变化(安卓版本需要小于5.0)  

scrollEnabled:是否启用可滚动选项卡 tabStyle:tab的样式  

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

labelStyle:label的样式  

iconStyle:图标样式  

实战演练

我们创建App.js,然后在index.ios.js文件引用该组件:

import App from ‘./App‘
export default class RNDemoTwo extends Component {
    render() {
        return (
            <App/>
        );
    }
}

现在来配置下App.js文件:

import {TabNavigator} from ‘react-navigation‘
import HelloViewCompnent from ‘./HelloViewComponent‘
import DetailComponent from ‘./DetailComponent‘
import ThreeComponent from ‘./Three‘
import CustTabBarItem from "./TabBarItem"

const SimpleApp = TabNavigator({
    Home: {
        screen: HelloViewCompnent,
        navigationOptions: ({navigation}) => ({
            tabBarVisible: true,
            tabBarLabel: ‘首页‘,
            tabBarIcon: ({focused, tintColor})=>(
                <CustTabBarItem
                    tintColor={tintColor}
                    focused={focused}
                    selectImage={{uri: ‘tabbar_home_select‘}}
                    normalImage={{uri: ‘tabbar_home‘}}
                />
            ),
        })
    },

    Detail: {
        screen: DetailComponent,
        navigationOptions: ({navigation}) => ({
            tabBarLabel: ‘消息‘,
            tabBarIcon: ({focused, tintColor})=>(
                <CustTabBarItem
                    tintColor={tintColor}
                    focused={focused}
                    selectImage={{uri: ‘tabbar_licai_select‘}}
                    normalImage={{uri: ‘tabbar_licai‘}}
                />
            ),
        })
    },

    Three: {
        screen: ThreeComponent,
        navigationOptions: ({navigation}) => ({
            tabBarLabel: ‘我的‘,
            tabBarIcon: ({focused, tintColor})=>(
                <CustTabBarItem
                    tintColor={tintColor}
                    focused={focused}
                    selectImage={{uri: ‘tabbar_my_select‘}}
                    normalImage={{uri: ‘tabbar_my‘}}
                />
            ),
        })
    }
},{
    tabBarPosition:‘bottom‘,
    swipeEnabled:false,
    animationEnabled:false,
    lazy:true,
    tabBarOptions:{
        activeTintColor:‘red‘,
        inactiveTintColor:‘black‘,
        style:{backgroundColor:‘#fff‘,},
        labelStyle: {
            fontSize: 16, // 文字大小
        },
    }
})

export default SimpleApp

可以看到我们导入了三个页面组件,一个CustTabBarItem
三个页面组件很简单,都类似,由于篇幅原因,只贴出一个就行了:

export default class HelloViewCompnent extends Component {

    render() {
        return (
            <View style={styles.container}>
                <Text style={styles.welcome}>
                    首页
                </Text>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: ‘center‘,
        alignItems: ‘center‘,
        backgroundColor: ‘white‘,
    },
    welcome: {
        fontSize: 20,
        textAlign: ‘center‘,
        margin: 10,
    },
});

最后,就是我们的TabBarItem.js文件了:

export default class TabBarItem extends Component {
    render(){
        return (
            <Image source={this.props.focused ? this.props.selectImage : this.props.normalImage}
            style={{tintColor: this.props.tintColor, width: 25, height: 25}}/>
        );
    }
}

保存代码,运行项目,不出意外,应该和使用TabBarIOS是一样的效果。

关于Image组件

由于这里我们都使用到<Image/>组件,这里就稍微讲一下。

  • Image:用于加载图片,可加载网络图片,也可以加载本地图片
  • Image常用属性
    source {uri: string}, number : 设置Image图片资源
    blurRadius number:让图片模糊
    defaultSource {uri: string, width: number, height:number, scale: number}, number 占位图片,在读取图片时默认显示的加载提示图片 
    
    resizeMode enum(‘cover‘, ‘contain‘, ‘stretch‘, ‘repeat‘,
    ‘center‘) 决定图片尺寸大小。 
    
    cover: 在保持图片宽高比的前提下缩放图片,直到宽度和高度都大于等于容器视图的尺寸(如果容器有padding内衬的话,则相应减去)。译注:这样图片完全覆盖甚至超出容器,容器中不留任何空白。 
    
    contain: 在保持图片宽高比的前提下缩放图片,直到宽度和高度都小于等于容器视图的尺寸(如果容器有padding内衬的话,则相应减去)。译注:这样图片完全被包裹在容器中,容器中可能留有空白 
    
    stretch: 拉伸图片且不维持宽高比,直到宽高都刚好填满容器。
    repeat: 重复平铺图片直到填满容器。图片会维持原始尺寸。仅iOS可用。
    center: 居中不拉伸。
  • 本地图片存放位置
      1. 直接放在RN项目中
      1. 可以放在ios项目中,放到images.xcassets文件中
      1. 可以放在android项目中(安卓中图片文字不能以数字开头,也不能有大写字母)
  • 如何加载本地图片
    • RN中加载资源:require(文件路径),用于加载RN中的资源,不管是图片,还是json都是一样的
    • uri:指定一个资源路径,就会自动加载
    • uri加载注意:通过uri加载资源,必须设置图片尺寸,否则不显示
    • 如果网络加载http图片,iOS默认不支持,需要开启App Transport

致谢

如果发现有错误的地方,欢迎各位指出,谢谢!

时间: 2024-10-13 04:38:12

React Native 系列(九)的相关文章

菜鸟窝React Native 系列教程-1.移动端开发趋势与未来

菜鸟窝React Native 系列教程-1.移动端开发趋势与未来 课程持续更新中..... 我是RichardCao,现任新美大酒店旅游事业群的Android Developer.如果你也有兴趣录制RN视频,请加入下面QQ群找我. 下载地址:https://pan.baidu.com/s/1c1XmE56 密码:shhw 首发地址:菜鸟窝-ReactNative学习板块 交流QQ群:576089067 课程目录:菜鸟窝React Native 系列教程

【REACT NATIVE 系列教程之十三】利用LISTVIEW与TEXTINPUT制作聊天/对话框&&获取组件实例常用的两种方式

本站文章均为 李华明Himi 原创,转载务必在明显处注明: 转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/react-native/2346.html 本篇Himi来利用ListView和TextInput这两种组件实现对话.聊天框. 首先需要准备的有几点:(组件的学习就不赘述了,简单且官方有文档) 1. 学习下 ListView: 官方示例:http://reactnative.cn/docs/0.27/tutorial.html#content

【REACT NATIVE 系列教程之二】创建自定义组件&&导入与使用示例

本站文章均为 李华明Himi 原创,转载务必在明显处注明: 转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/react-native/2219.html 在上一篇  [REACT NATIVE 系列教程之一]触摸事件的两种形式与四种TOUCHABLE组件详解 中的最后介绍了如何使用Touchable的四种组件进行监听触摸事件.  那么紧接着我们利用Touchable来包装一个带图片的Button组件,且设计成可接受很多自定义参数. 一:创建我们自定义

【REACT NATIVE 系列教程之十二】REACT NATIVE(JS/ES)与IOS(OBJECT-C)交互通信

一用到跨平台的引擎必然要有引擎与各平台原生进行交互通信的需要.那么Himi先讲解React Native与iOS之间的通信交互. 本篇主要分为两部分讲解:(关于其中讲解的OC语法等不介绍,不懂的请自行学习) 1. React Native 访问iOS 2. iOS访问React Native     一:React Native 访问iOS 1. 我们想要JS调用OC函数,就要实现一个"RCTBridgeModule"协议的Objective-C类 所以首先我们先创建一个oc新类,  

【REACT NATIVE 系列教程之十一】插件的安装、使用与更新(示例:REACT-NATIVE-TAB-NAVIGATOR)

本站文章均为 李华明Himi 原创,转载务必在明显处注明: 转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/react-native/2294.html 本篇主要来详细介绍如何安装.升级插件及讲解一个react-native-tab-navigator的示例. 首先推荐一个插件网站:https://www.npmjs.com     (此插件属于半官方维护的) 本文举例使用的插件:react-native-tab-navigator ,选项卡形式的导

【REACT NATIVE 系列教程之七】统一ANDROID与IOS两个平台的程序入口&&区分平台的组件简介

本站文章均为 李华明Himi 原创,转载务必在明显处注明: 转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/react-native/2260.html       本篇介绍两个细节:       1. 关于如何将index.android.js 与index.ios.js统一管理起来.       2.  Platform 组件的简单介绍与使用   一:将index.android.js 与index.ios.js统一管理起来. 由于React本身

【REACT NATIVE 系列教程之九】REACT NATIVE版本升级步骤与注意事项!

本站文章均为 李华明Himi 原创,转载务必在明显处注明: 转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/react-native/2288.html 由于React Native处于快速迭代发展中,因此组件功能的扩展.语法的变更也将会有较大的区别,因此升级版本则属于务必掌握的了. 昨天Himi刚从0.23版本升级到0.26,升级的主要原因有两点: 1. 一些组件在最新版本中加入了很多新的属性,例如0.23版本中Modal动画没有最新的属性: an

【REACT NATIVE 系列教程之一】触摸事件的两种形式与四种TOUCHABLE组件详解

本站文章均为 李华明Himi 原创,转载务必在明显处注明: 转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/react-native/2203.html 本文是RN(React Native)系列教程第一篇,当然也要给自己的群做个广告:   React Native @Himi :126100395  刚创建的群,欢迎一起学习.讨论.进步. 本文主要讲解两点: 1.   PanResponder:触摸事件,用以获取用户手指所在屏幕的坐标(x,y)或触

React Native 系列(六)

前言 本系列是基于React Native版本号0.44.3写的.在我们之前的通过props实现组件间传值的时候,大家有没有发现在父组件传递值过去,在子控件获取props的时候没有提示,那么如何能实现让其有提示呢?这篇文章将带领大家去认识一下PropTypes这个玩意. PropTypes 问题: 在自定义组件的时候,通常需要暴露属性出去,并且设置属性类型,外界在使用自定义组件的属性的时候,需要有自动提示属性功能. 解决: 使用PropTypes PropTypes用处: 可以实现类型检查,当传