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 (
<NCINavigation/>
);
}
}
const NCIAppTabBar = createBottomTabNavigator({
/*首页*/
Home: {
screen:Home,
navigationOptions: {
tabBarLabel:'首页',
tabBarIcon:({tintColor})=>(
<Image source={{uri:'icon_car_active'}} style={[styles.tabIcon, {tintColor:tintColor}]} />
),
},
},
/*订单*/
Order: {
screen:Order,
navigationOptions:{
tabBarLabel:'订单',
tabBarIcon:({tintColor})=>(
<Image source={{uri:'icon_bill'}} style={[styles.tabIcon, {tintColor:tintColor}]} />
),
},
},
/*我的*/
Mine: {
screen:Mine,
navigationOptions:{
tabBarLabel:'我的',
tabBarIcon:({tintColor})=>(
<Image source={{uri:'icon_user'}} style={[styles.tabIcon, {tintColor: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;
// iPhoneX
const X_WIDTH = 375;
const X_HEIGHT = 812;
// screen
const 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 (
<View style={styles.navView}>
<View style={styles.statusView}></View>
<View style={styles.titleView}>
<Text style={styles.titleText}>{this.props.titleName}</Text>
</View>
</View>
);
}
}
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)',
}
});只能以这种方式来解决了,有好的指导意见求指教。
实现效果如下: