一、自定義的思路
iOS中的TabBarController確實已經很強大了,大部分主流iOS應用都會采用。但是往往也不能滿足全部的需求,因此需要自定義TabBar,自定義需要對系統的TabBar工作方式有很好的理解,自定義需要勇氣。
自定義TabBar的原則:盡量利用系統自帶TabBar,只改需要改的地方。
二、自定義TabBar的總體過程 1.先把自帶的TabBar條給取消了 2.自己做一個view,上面放幾個按鈕,設定按鈕的點擊事件.並設置selectIndex。 3.關聯各個子viewController,覆蓋相關事件。
三、細節很重要
1. 讓自己創建的按鈕關聯到viewController: ?用tabbar的selectedIndex屬性.設置這個屬性就行了. 2. 取消系統的高亮: ?可以自定義一個按鈕.重寫裡面的setHighhighted方法,什麼也不做就行了.(如果調用super就相當於沒寫) 3. 關於幾個按鈕只選中一個的方法: ?設置一個屬性,記錄上一個選中的按鈕. ?點擊當前按鈕時,把上一個按鈕設置為未選中,並把當前按鈕設置為選中,最後把當前按鈕賦值給上一個按鈕.
#import@interface XNTabBarController : UITabBarController @end
XNTabBarController.m
// // XNTabBarController.m // // // Created by neng on 14-6-19. // Copyright (c) 2014年 neng. All rights reserved. // #import "XNTabBarController.h" #import "Common.h" #import "XNTabBarButton.h" @interface XNTabBarController () /** * 設置之前選中的按鈕 */ @property (nonatomic, weak) UIButton *selectedBtn; @end @implementation XNTabBarController - (void)viewDidLoad { [super viewDidLoad]; //下面兩個方法在開發中是經常會用到的 // NSLog(@"%s",__func__); // NSLog(@"%@",self.view.subviews); //能打印出所有子視圖,和其frame LogFun; LogSubviews(self.view); //刪除現有的tabBar CGRect rect = self.tabBar.frame; [self.tabBar removeFromSuperview]; //移除TabBarController自帶的下部的條 //測試添加自己的視圖 UIView *myView = [[UIView alloc] init]; myView.frame = rect; myView.backgroundColor = [UIColor redColor]; [self.view addSubview:myView]; for (int i = 0; i < 5; i++) { //UIButton *btn = [[UIButton alloc] init]; XNTabBarButton *btn = [[XNTabBarButton alloc] init]; NSString *imageName = [NSString stringWithFormat:@"TabBar%d", i + 1]; NSString *imageNameSel = [NSString stringWithFormat:@"TabBar%dSel", i + 1]; [btn setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal]; [btn setImage:[UIImage imageNamed:imageNameSel] forState:UIControlStateSelected]; CGFloat x = i * myView.frame.size.width / 5; btn.frame = CGRectMake(x, 0, myView.frame.size.width / 5, myView.frame.size.height); [myView addSubview:btn]; btn.tag = i;//設置按鈕的標記, 方便來索引當前的按鈕,並跳轉到相應的視圖 //帶參數的監聽方法記得加"冒號" [btn addTarget:self action:@selector(clickBtn:) forControlEvents:UIControlEventTouchUpInside]; //設置剛進入時,第一個按鈕為選中狀態 if (0 == i) { btn.selected = YES; self.selectedBtn = btn; //設置該按鈕為選中的按鈕 } } } /** * 自定義TabBar的按鈕點擊事件 */ - (void)clickBtn:(UIButton *)button { //1.先將之前選中的按鈕設置為未選中 self.selectedBtn.selected = NO; //2.再將當前按鈕設置為選中 button.selected = YES; //3.最後把當前按鈕賦值為之前選中的按鈕 self.selectedBtn = button; //4.跳轉到相應的視圖控制器. (通過selectIndex參數來設置選中了那個控制器) self.selectedIndex = button.tag; } @end
XNTabBarButton.h
#import@interface XNTabBarButton : UIButton @end
XNTabBarButton.m
#import "XNTabBarButton.h" @implementation XNTabBarButton /**什麼也不做就可以取消系統按鈕的高亮狀態*/ - (void)setHighlighted:(BOOL)highlighted{ // [super setHighlighted:highlighted]; } @end
重構的目的是把代碼放到他最該到的地方去. 提高可讀寫與可拓展性。
2、關於控件的布局代碼: ?建議寫在layoutSubviews方法中. ?不要忘記寫super方法 ?將設置x,y,frame等寫在這裡面. 3、將自定義的Tabbar添加為系統TabBar的子視圖,這樣TabBar的切換自動隱藏/滑動功能就不用自己做了. (hidebottombaronpush)
#import@class XNTabBar; @protocol XNTabBarDelegate /** * 工具欄按鈕被選中, 記錄從哪裡跳轉到哪裡. (方便以後做相應特效) */ - (void) tabBar:(XNTabBar *)tabBar selectedFrom:(NSInteger) from to:(NSInteger)to; @end @interface XNTabBar : UIView @property(nonatomic,weak) id delegate; /** * 使用特定圖片來創建按鈕, 這樣做的好處就是可擴展性. 拿到別的項目裡面去也能換圖片直接用 * * @param image 普通狀態下的圖片 * @param selectedImage 選中狀態下的圖片 */ -(void)addButtonWithImage:(UIImage *)image selectedImage:(UIImage *) selectedImage; @end
XNTabBar.m
// // XNTabBar.m // // Created by neng on 14-6-19. // Copyright (c) 2014年 neng. All rights reserved. // #import "XNTabBar.h" #import "XNTabBarButton.h" @interface XNTabBar () /** * 設置之前選中的按鈕 */ @property (nonatomic, weak) UIButton *selectedBtn; @end @implementation XNTabBar /** * 在這個方法裡寫控件初始化的東西, 調用init方法時會調用 */ //- (id)initWithFrame:(CGRect)frame { // if (self = [super initWithFrame:frame]) { // //添加按鈕 // for (int i = 0; i < 5; i++) { //取消掉特定的數字 // //UIButton *btn = [[UIButton alloc] init]; // XNTabBarButton *btn = [[XNTabBarButton alloc] init]; // // NSString *imageName = [NSString stringWithFormat:@"TabBar%d", i + 1]; // NSString *imageNameSel = [NSString stringWithFormat:@"TabBar%dSel", i + 1]; // // [btn setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal]; // [btn setImage:[UIImage imageNamed:imageNameSel] forState:UIControlStateSelected]; // // [self addSubview:btn]; // // btn.tag = i; //設置按鈕的標記, 方便來索引當前的按鈕,並跳轉到相應的視圖 // // //帶參數的監聽方法記得加"冒號" // [btn addTarget:self action:@selector(clickBtn:) forControlEvents:UIControlEventTouchUpInside]; // // if (0 == i) { // [self clickBtn:btn]; // } // } // } // return self; //} - (void)addButtonWithImage:(UIImage *)image selectedImage:(UIImage *)selectedImage { UIButton *btn = [[UIButton alloc] init]; [btn setImage:image forState:UIControlStateNormal]; [btn setImage:selectedImage forState:UIControlStateSelected]; [self addSubview:btn]; //帶參數的監聽方法記得加"冒號" [btn addTarget:self action:@selector(clickBtn:) forControlEvents:UIControlEventTouchUpInside]; //如果是第一個按鈕, 則選中(按順序一個個添加) if (self.subviews.count == 1) { [self clickBtn:btn]; } } /**專門用來布局子視圖, 別忘了調用super方法*/ - (void)layoutSubviews { [super layoutSubviews]; int count = self.subviews.count; for (int i = 0; i < count; i++) { //取得按鈕 UIButton *btn = self.subviews[i]; btn.tag = i; //設置按鈕的標記, 方便來索引當前的按鈕,並跳轉到相應的視圖 CGFloat x = i * self.bounds.size.width / count; CGFloat y = 0; CGFloat width = self.bounds.size.width / count; CGFloat height = self.bounds.size.height; btn.frame = CGRectMake(x, y, width, height); } } /** * 自定義TabBar的按鈕點擊事件 */ - (void)clickBtn:(UIButton *)button { //1.先將之前選中的按鈕設置為未選中 self.selectedBtn.selected = NO; //2.再將當前按鈕設置為選中 button.selected = YES; //3.最後把當前按鈕賦值為之前選中的按鈕 self.selectedBtn = button; //卻換視圖控制器的事情,應該交給controller來做 //最好這樣寫, 先判斷該代理方法是否實現 if ([self.delegate respondsToSelector:@selector(tabBar:selectedFrom:to:)]) { [self.delegate tabBar:self selectedFrom:self.selectedBtn.tag to:button.tag]; } //4.跳轉到相應的視圖控制器. (通過selectIndex參數來設置選中了那個控制器) //self.selectedIndex = button.tag; } @end
// // XNTabBarController.m // // Created by neng on 14-6-19. // Copyright (c) 2014年 neng. All rights reserved. // #import "XNTabBarController.h" #import "XNTabBarButton.h" #import "XNTabBar.h" @interface XNTabBarController ()/** * 設置之前選中的按鈕 */ @property (nonatomic, weak) UIButton *selectedBtn; @end @implementation XNTabBarController - (void)viewDidLoad { [super viewDidLoad]; //下面兩個方法在開發中是經常會用到的 // NSLog(@"%s",__func__); // NSLog(@"%@",self.view.subviews); //能打印出所有子視圖,和其frame // LogFun; // LogSubviews(self.view); //Hell //刪除現有的tabBar CGRect rect = self.tabBar.bounds; //這裡要用bounds來加, 否則會加到下面去.看不見 LogFrame(self.tabBar); //[self.tabBar removeFromSuperview]; //移除TabBarController自帶的下部的條 //測試添加自己的視圖 XNTabBar *myView = [[XNTabBar alloc] init]; //設置代理必須改掉前面的類型,不能用UIView myView.delegate = self; //設置代理 myView.frame = rect; [self.tabBar addSubview:myView]; //添加到系統自帶的tabBar上, 這樣可以用的的事件方法. 而不必自己去寫 //為控制器添加按鈕 for (int i=0; i 自定義後的效果圖:
例子源碼下載 : http://download.csdn.net/detail/xn4545945/7572263
轉載請注明出處:http://blog.csdn.net/xn4545945