TabBar控件在移动端App中使用的频率比较高,故今天来探讨一下React Native中的实现方式。查阅资料发现TabNavigator方法已经被废弃,需要引入文件react-navigation文件,下载对应资源的方法:
导入该资源文件后,运行Xcode会报错,需要执行npm install操作,有时候执行初始化操作后会出现以下错误:
解决办法:
运行npm cache clean --force 完美解决
OK。配置结束后,根据我之前iOS开发经验,需要用TabBarController来管理多个由NavigationController管理的一系列ViewController。那么问题来了,切换场景得时候可能有隐藏TabBar的需求,按照刚才所说的方法,我需要set一个值来控制tabbar的height
和overflow
,又由于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 (); }}const NCIAppTabBar = createBottomTabNavigator({ /*首页*/ Home: { screen:Home, navigationOptions: { tabBarLabel:'首页', tabBarIcon:({tintColor})=>( ), }, }, /*订单*/ Order: { screen:Order, navigationOptions:{ tabBarLabel:'订单', tabBarIcon:({tintColor})=>( ), }, }, /*我的*/ Mine: { screen:Mine, navigationOptions:{ tabBarLabel:'我的', tabBarIcon:({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;// iPhoneXconst X_WIDTH = 375;const X_HEIGHT = 812;// screenconst 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 (); }}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)', }});复制代码 {this.props.titleName}
只能以这种方式来解决了,有好的指导意见求指教。
实现效果如下: