你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> [iOS]自定義TabBarController

[iOS]自定義TabBarController

編輯:IOS開發綜合

一、自定義的思路

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); //能打印出所有子視圖,和其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

五、代碼重構

 

 

重構的目的是把代碼放到他最該到的地方去. 提高可讀寫與可拓展性。
對控件的重構要保證可重用性. 做到封裝做其他應用時,可以直接拿過去用的地步.
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


	//刪除現有的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

 

 

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved