##前言
>最近的項(xiàng)目中有需求在tabbar中間添加凸起按鈕,并且點(diǎn)擊時按鈕要旋轉(zhuǎn),看了仿斗魚的凸起,點(diǎn)擊后是present出來View,而不是像常規(guī)的tabbar上添加一個頁面,所以不符合要求,經(jīng)過一段摸索最后得的一個比較好的效果
##需求分析
* tabbar有5個item,每個對應(yīng)一個頁面
* 中間item為凸起按鈕
* 中間按鈕點(diǎn)擊后旋轉(zhuǎn)
##效果實(shí)現(xiàn)
* 設(shè)置5個item
我們一步步來解決這個問題,首先創(chuàng)建MCTabBarController繼承UITabBarController,然后和常規(guī)一樣創(chuàng)建5個item,中間的按鈕不設(shè)置圖片,代碼如下
//MCTabBarController.m
//添加子控制器
-?(void)addChildViewControllers{
//圖片大小建議32*32
[self?addChildrenViewController:[[ViewController?alloc]?init]?andTitle:@"首頁"andImageName:@"tab1_n"andSelectImage:@"tab1_p"];
[self?addChildrenViewController:[[ViewController?alloc]?init]?andTitle:@"擴(kuò)展"andImageName:@"tab2_n"andSelectImage:@"tab2_p"];
//中間這個不設(shè)置東西,只占位
[self?addChildrenViewController:[[ViewController?alloc]?init]?andTitle:@"旋轉(zhuǎn)"andImageName:@""andSelectImage:@""];
[self?addChildrenViewController:[[ViewController?alloc]?init]?andTitle:@"發(fā)現(xiàn)"andImageName:@"tab3_n"andSelectImage:@"tab3_p"];
[self?addChildrenViewController:[[ViewController?alloc]?init]?andTitle:@"我"andImageName:@"tab4_n"andSelectImage:@"tab4_p"];
}
-?(void)addChildrenViewController:(UIViewController?*)childVC?andTitle:(NSString?*)title?andImageName:(NSString?*)imageName?andSelectImage:(NSString?*)selectedImage{
childVC.tabBarItem.image?=?[UIImage?imageNamed:imageName];
childVC.tabBarItem.selectedImage?=??[UIImage?imageNamed:selectedImage];
childVC.title?=?title;
BaseNavigationController?*baseNav?=?[[BaseNavigationController?alloc]?initWithRootViewController:childVC];
[self?addChildViewController:baseNav];
}
這樣實(shí)現(xiàn)的效果如下圖所示
[圖一.png]
* 添加凸起按鈕
我們可以在UITabBar上添加我們的凸起按鈕,讓他的位置在沒有設(shè)置的中間按鈕偏上,按鈕的點(diǎn)擊和中間按鈕點(diǎn)擊綁定,這里直接在MCTabBarController.m中添加會有問題
1、因?yàn)橥蛊鸢粹o的frame超出了UITabBar的frame,這樣超出的區(qū)域點(diǎn)擊按鈕會沒有響應(yīng)(圖二紅框區(qū)域),原因和解決辦法詳情參考我的這篇[iOS UIButton 點(diǎn)擊無響應(yīng)的解決辦法],由于要在UITabBar上添加凸起按鈕,并且處理點(diǎn)擊無效的問題,所以這里創(chuàng)建了MCTabBar繼承UITabBar
[圖二.png]
2、由于UITabBar是readonly的,所以我們不能直接對他進(jìn)行賦值,這里利用KVC訪問私有變量將MCTabBar賦值給"tabBar"
**具體實(shí)現(xiàn)**
MCTabBar
```
#import
@interfaceMCTabBar?:?UITabBar
@property?(nonatomic,?strong)?UIButton?*centerBtn;//中間按鈕
@end
```
```
@implementation?MCTabBar
-?(instancetype)init{
if(self?=?[superinit]){
[self?initView];
}
returnself;
}
-?(void)initView{
_centerBtn?=?[UIButton?buttonWithType:UIButtonTypeCustom];
//??設(shè)定button大小為適應(yīng)圖片
UIImage?*normalImage?=?[UIImage?imageNamed:@"tabbar_add"];
_centerBtn.frame?=?CGRectMake(0,0,?normalImage.size.width,?normalImage.size.height);
[_centerBtn?setImage:normalImage?forState:UIControlStateNormal];
//去除選擇時高亮
_centerBtn.adjustsImageWhenHighlighted?=?NO;
//根據(jù)圖片調(diào)整button的位置(圖片中心在tabbar的中間最上部,這個時候由于按鈕是有一部分超出tabbar的,所以點(diǎn)擊無效,要進(jìn)行處理)
_centerBtn.frame?=?CGRectMake(([UIScreen?mainScreen].bounds.size.width?-?normalImage.size.width)/2.0,?-?normalImage.size.height/2.0,?normalImage.size.width,?normalImage.size.height);
[self?addSubview:_centerBtn];
}
//處理超出區(qū)域點(diǎn)擊無效的問題
-?(UIView?*)hitTest:(CGPoint)point?withEvent:(UIEvent?*)event{
UIView?*view?=?[superhitTest:point?withEvent:event];
if(view?==?nil){
//轉(zhuǎn)換坐標(biāo)
CGPoint?tempPoint?=?[self.centerBtn?convertPoint:point?fromView:self];
//判斷點(diǎn)擊的點(diǎn)是否在按鈕區(qū)域內(nèi)
if(CGRectContainsPoint(self.centerBtn.bounds,?tempPoint)){
//返回按鈕
return_centerBtn;
}
}
returnview;
}
```
利用KVC賦值
```
//MCTabBarController.m
-?(void)viewDidLoad?{
[superviewDidLoad];
_mcTabbar?=?[[MCTabBar?alloc]?init];
[_mcTabbar.centerBtn?addTarget:self?action:@selector(buttonAction:)?forControlEvents:UIControlEventTouchUpInside];
//選中時的顏色
_mcTabbar.tintColor?=?[UIColor?colorWithRed:27.0/255.0green:118.0/255.0blue:208/255.0alpha:1];
//透明設(shè)置為NO,顯示白色,view的高度到tabbar頂部截止,YES的話到底部
_mcTabbar.translucent?=?NO;
//利用KVC?將自己的tabbar賦給系統(tǒng)tabBar
[self?setValue:_mcTabbar?forKeyPath:@"tabBar"];
self.delegate?=?self;
[self?addChildViewControllers];
}
```
* 點(diǎn)擊旋轉(zhuǎn)
在中間按鈕的點(diǎn)擊事件執(zhí)行時旋轉(zhuǎn)第二個index,然后執(zhí)行旋轉(zhuǎn)動畫,
在tabbar的代理事件中監(jiān)聽旋中中間按鈕的事件,然后執(zhí)行旋轉(zhuǎn)動畫,其他按鈕則移除動畫,代碼如下
```
-?(void)buttonAction:(UIButton?*)button{
self.selectedIndex?=2;//關(guān)聯(lián)中間按鈕
[self?rotationAnimation];
}
//tabbar選擇時的代理
-?(void)tabBarController:(UITabBarController?*)tabBarController?didSelectViewController:(UIViewController?*)viewController{
if(tabBarController.selectedIndex?==2){//選中中間的按鈕
[self?rotationAnimation];
}else{
[_mcTabbar.centerBtn.layer?removeAllAnimations];
}
}
//旋轉(zhuǎn)動畫
-?(void)rotationAnimation{
CABasicAnimation?*rotationAnimation?=?[CABasicAnimation?animationWithKeyPath:@"transform.rotation.z"];
rotationAnimation.toValue?=?[NSNumber?numberWithFloat:M_PI*2.0];
rotationAnimation.duration?=3.0;
rotationAnimation.repeatCount?=?HUGE;
[_mcTabbar.centerBtn.layer?addAnimation:rotationAnimation?forKey:@"key"];
}
```
* 其他
這里寫了BaseNavigationController繼承自UINavigationController,處理了push后隱藏底部UITabBar的情況,并解決了iPhonX上push時UITabBar上移的問題。