iOS開發-實現TabBar中間凸起按鈕、不規則按鈕(自定義TabBar)
阿新 • • 發佈:2019-01-02
效果:
PS:這裡需要用到UIView一個分類的一些屬性,參考http://blog.csdn.net/doubleface999/article/details/79085764,圖示素材等自行上網找或者自己設計,這裡就不提供了。最後在StoryBoard中選擇TabBarController對應下面自定義的TabBarController即可
自定義TabBar:
MyTabBar.h
1 #import <UIKit/UIKit.h> 2 3 @class MyTabBar; 4 5 //MyTabBar的代理必須實現addButtonClick,以響應中間“+”按鈕的點選事件6 @protocol MyTabBarDelegate <NSObject> 7 8 -(void)addButtonClick:(MyTabBar *)tabBar; 9 10 @end 11 12 @interface MyTabBar : UITabBar 13 14 //指向MyTabBar的代理 15 @property (nonatomic,weak) id<MyTabBarDelegate> myTabBarDelegate; 16 17 @end
MyTabBar.m
1 #import "MyTabBar.h" 2 #import"UIView+Category.h" 3 4 #define AddButtonMargin 10 5 6 @interface MyTabBar() 7 8 //指向中間“+”按鈕 9 @property (nonatomic,weak) UIButton *addButton; 10 //指向“新增”標籤 11 @property (nonatomic,weak) UILabel *addLabel; 12 13 @end 14 15 @implementation MyTabBar 16 17 /* 18 // Only override drawRect: if you perform custom drawing.19 // An empty implementation adversely affects performance during animation. 20 - (void)drawRect:(CGRect)rect { 21 // Drawing code 22 } 23 */ 24 25 -(instancetype)initWithFrame:(CGRect)frame 26 { 27 if(self = [super initWithFrame:frame]) 28 { 29 //建立中間“+”按鈕 30 UIButton *addBtn = [[UIButton alloc] init]; 31 //設定預設背景圖片 32 [addBtn setBackgroundImage:[UIImage imageNamed:@"AddButtonIcon"] forState:UIControlStateNormal]; 33 //設定按下時背景圖片 34 [addBtn setBackgroundImage:[UIImage imageNamed:@"AddButtonIcon-Active"] forState:UIControlStateHighlighted]; 35 //新增響應事件 36 [addBtn addTarget:self action:@selector(addBtnDidClick) forControlEvents:UIControlEventTouchUpInside]; 37 //將按鈕新增到TabBar 38 [self addSubview:addBtn]; 39 40 self.addButton = addBtn; 41 } 42 return self; 43 } 44 45 //響應中間“+”按鈕點選事件 46 -(void)addBtnDidClick 47 { 48 if([self.myTabBarDelegate respondsToSelector:@selector(addButtonClick:)]) 49 { 50 [self.myTabBarDelegate addButtonClick:self]; 51 } 52 } 53 54 -(void)layoutSubviews 55 { 56 [super layoutSubviews]; 57 58 //去掉TabBar上部的橫線 59 for (UIView *view in self.subviews) 60 { 61 if ([view isKindOfClass:[UIImageView class]] && view.bounds.size.height <= 1) //橫線的高度為0.5 62 { 63 UIImageView *line = (UIImageView *)view; 64 line.hidden = YES; 65 } 66 } 67 68 //設定“+”按鈕的位置 69 self.addButton.centerX = self.centerX; 70 self.addButton.centerY = self.height * 0.5 - 1.5 * AddButtonMargin; 71 //設定“+”按鈕的大小為圖片的大小 72 self.addButton.size = CGSizeMake(self.addButton.currentBackgroundImage.size.width, self.addButton.currentBackgroundImage.size.height); 73 74 //建立並設定“+”按鈕下方的文字為“新增” 75 UILabel *addLbl = [[UILabel alloc] init]; 76 addLbl.text = @"新增"; 77 addLbl.font = [UIFont systemFontOfSize:10]; 78 addLbl.textColor = [UIColor grayColor]; 79 [addLbl sizeToFit]; 80 81 //設定“新增”label的位置 82 addLbl.centerX = self.addButton.centerX; 83 addLbl.centerY = CGRectGetMaxY(self.addButton.frame) + 0.5 * AddButtonMargin + 0.5; 84 85 [self addSubview:addLbl]; 86 87 self.addLabel = addLbl; 88 89 int btnIndex = 0; 90 //系統自帶的按鈕型別是UITabBarButton,找出這些型別的按鈕,然後重新排布位置,空出中間的位置 91 Class class = NSClassFromString(@"UITabBarButton"); 92 for (UIView *btn in self.subviews) {//遍歷TabBar的子控制元件 93 if ([btn isKindOfClass:class]) {//如果是系統的UITabBarButton,那麼就調整子控制元件位置,空出中間位置 94 //每一個按鈕的寬度等於TabBar的三分之一 95 btn.width = self.width / 3; 96 97 btn.x = btn.width * btnIndex; 98 99 btnIndex++; 100 //如果索引是1(即“+”按鈕),直接讓索引加一 101 if (btnIndex == 1) { 102 btnIndex++; 103 } 104 105 } 106 } 107 //將“+”按鈕放到檢視層次最前面 108 [self bringSubviewToFront:self.addButton]; 109 } 110 111 //重寫hitTest方法,去監聽"+"按鈕和“新增”標籤的點選,目的是為了讓凸出的部分點選也有反應 112 - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { 113 114 //這一個判斷是關鍵,不判斷的話push到其他頁面,點選“+”按鈕的位置也是會有反應的,這樣就不好了 115 //self.isHidden == NO 說明當前頁面是有TabBar的,那麼肯定是在根控制器頁面 116 //在根控制器頁面,那麼我們就需要判斷手指點選的位置是否在“+”按鈕或“新增”標籤上 117 //是的話讓“+”按鈕自己處理點選事件,不是的話讓系統去處理點選事件就可以了 118 if (self.isHidden == NO) 119 { 120 121 //將當前TabBar的觸控點轉換座標系,轉換到“+”按鈕的身上,生成一個新的點 122 CGPoint newA = [self convertPoint:point toView:self.addButton]; 123 //將當前TabBar的觸控點轉換座標系,轉換到“新增”標籤的身上,生成一個新的點 124 CGPoint newL = [self convertPoint:point toView:self.addLabel]; 125 126 //判斷如果這個新的點是在“+”按鈕身上,那麼處理點選事件最合適的view就是“+”按鈕 127 if ( [self.addButton pointInside:newA withEvent:event]) 128 { 129 return self.addButton; 130 } 131 //判斷如果這個新的點是在“新增”標籤身上,那麼也讓“+”按鈕處理事件 132 else if([self.addLabel pointInside:newL withEvent:event]) 133 { 134 return self.addButton; 135 } 136 else 137 {//如果點不在“+”按鈕身上,直接讓系統處理就可以了 138 139 return [super hitTest:point withEvent:event]; 140 } 141 } 142 else 143 { 144 //TabBar隱藏了,那麼說明已經push到其他的頁面了,這個時候還是讓系統去判斷最合適的view處理就好了 145 return [super hitTest:point withEvent:event]; 146 } 147 } 148 149 @end
自定義TabBarController:
MyTabBarController.h
1 #import <UIKit/UIKit.h> 2 3 @interface MyTabBarController : UITabBarController 4 5 @end
MyTabBarController.m
1 #import "MyTabBarController.h" 2 #import "MyTabBar.h" 3 4 5 @interface MyTabBarController () <MyTabBarDelegate> //實現自定義TabBar協議 6 7 @end 8 9 @implementation MyTabBarController 10 11 - (void)viewDidLoad { 12 [super viewDidLoad]; 13 // Do any additional setup after loading the view. 14 15 //設定TabBar上第一個Item(明細)選中時的圖片 16 UIImage *listActive = [UIImage imageNamed:@"ListIcon - Active(blue)"]; 17 UITabBarItem *listItem = self.tabBar.items[0]; 18 //始終按照原圖片渲染 19 listItem.selectedImage = [listActive imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; 20 21 22 //設定TabBar上第二個Item(報表)選中時的圖片 23 UIImage *chartActive = [UIImage imageNamed:@"ChartIcon - Active(blue)"]; 24 UITabBarItem *chartItem = self.tabBar.items[1]; 25 //始終按照原圖片渲染 26 chartItem.selectedImage = [chartActive imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; 27 28 //建立自定義TabBar 29 MyTabBar *myTabBar = [[MyTabBar alloc] init]; 30 myTabBar.myTabBarDelegate = self; 31 32 //利用KVC替換預設的TabBar 33 [self setValue:myTabBar forKey:@"tabBar"]; 34 } 35 36 37 -(void)viewDidLayoutSubviews 38 { 39 [super viewDidLayoutSubviews]; 40 //設定TabBar的TintColor 41 self.tabBar.tintColor = [UIColor colorWithRed:89/255.0 green:217/255.0 blue:247/255.0 alpha:1.0]; 42 } 43 44 - (void)didReceiveMemoryWarning { 45 [super didReceiveMemoryWarning]; 46 // Dispose of any resources that can be recreated. 47 } 48 49 50 51 #pragma mark - MyTabBarDelegate 52 -(void)addButtonClick:(MyTabBar *)tabBar 53 { 54 //測試中間“+”按鈕是否可以點選並處理事件 55 UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"test" message:@"Test" preferredStyle:UIAlertControllerStyleAlert]; 56 UIAlertAction *action = [UIAlertAction actionWithTitle:@"test" style:UIAlertActionStyleDefault handler:nil]; 57 [controller addAction:action]; 58 [self presentViewController:controller animated:YES completion:nil]; 59 60 } 61 62 @end