[iOS]自訂TabBarController

來源:互聯網
上載者:User

一、自訂的思路

iOS中的TabBarController確實已經很強大了,大部分主流iOS應用都會採用。但是往往也不能滿足全部的需求,因此需要自訂TabBar,自訂需要對系統的TabBar工作方式有很好的理解,自訂需要勇氣。

自訂TabBar的原則:盡量利用系統內建TabBar,只改需要改的地方。

 

 

二、自訂TabBar的總體過程 1.先把內建的TabBar條給取消了 2.自己做一個view,上面放幾個按鈕,設定按鈕的點擊事件.並設定selectIndex。 3.關聯各個子viewController,覆蓋相關事件。

 

三、細節很重要

 

1. 讓自己建立的按鈕關聯到viewController: ?用tabbar的selectedIndex屬性.設定這個屬性就行了. 2. 取消系統的高亮: ?可以自訂一個按鈕.重寫裡面的setHighhighted方法,什麼也不做就行了.(如果調用super就相當於沒寫) 3. 關於幾個按鈕只選中一個的方法: ?設定一個屬性,記錄上一個選中的按鈕. ?點擊當前按鈕時,把上一個按鈕設定為未選中,並把當前按鈕設定為選中,最後把當前按鈕賦值給上一個按鈕.
四、初步自訂 直接上代碼,詳見注釋。 XNTabBarController.h

 

 

#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); //能列印出所有子視圖,和其frameLogFun;LogSubviews(self.view);//刪除現有的tabBarCGRect 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

五、代碼重構

 

 

重構的目的是把代碼放到他最該到的地方去. 提高可讀寫與可拓展性。
對控制項的重構要保證可重用性. 做到封裝做其他應用時,可以直接拿過去用的地步.
tips : 1、關於init與initWithFrame: ?在對象初始化調用init時,會調用initWithFrame方法. ?Init與initWithFrame都會被調用. ?建議自訂控制項不要重寫init方法,需要初始化時重寫initWithFrame方法. ?好處:其他人調用無論是調用init,還是調用initWithFrame都會調用initWithFrame方法.

 

2、關於控制項的布局代碼: ?建議寫在layoutSubviews方法中. ?不要忘記寫super方法 ?將設定x,y,frame等寫在這裡面. 3、將自訂的Tabbar添加為系統TabBar的子視圖,這樣TabBar的切換自動隱藏/滑動功能就不用自己做了. (hidebottombaronpush)
重構後的代碼如下: 將自訂的TabBar單獨建立,並將代碼移過去。 設定代理方法,工具列按鈕被選中,記錄從哪裡跳轉到哪裡.
XNTabBar.h

 

 

#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經過修改後,注釋了原先的代碼。

 

 

////  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//刪除現有的tabBarCGRect rect = self.tabBar.bounds; //這裡要用bounds來加, 否則會加到下面去.看不見    LogFrame(self.tabBar);//[self.tabBar removeFromSuperview];  //移除TabBarController內建的下部的條//測試添加自己的視圖XNTabBar *myView = [[XNTabBar alloc] init]; //設定代理必須改掉前面的類型,不能用UIViewmyView.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

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.