首先說明一下為什么要自定義TabBar
默認(rèn)TabBar有圖片和文字,如果素材是圖文分開的,那么一般不再需要自定義TabBar,如果素材是圖文一起的,不設(shè)置文字,只設(shè)置了TabBar的圖片,那么實(shí)現(xiàn)的效果就會(huì)片上方,留出文字的空白部分,如圖:
所以這種情況下一般需要自定義TabBar:
還有不同IOS下,TabBar的樣式存在差別,如IOS6的擬物化,IOS7開始扁平化,如果需要支持多版本,同時(shí)達(dá)到樣式一致,也可以通過自定義的方式實(shí)現(xiàn)(這種情況可能不會(huì)遇到,一般只要保證支持三個(gè)大版本就可以了)
先創(chuàng)建一個(gè)類,繼承自UIView
@class JSTabBarView;
@protocol TabBarViewSelectedIndexDelegate <NSObject>
//View中添加Button實(shí)現(xiàn)點(diǎn)擊,此時(shí)還無法切換控制器,所以這里用到了代理,在創(chuàng)建Button的時(shí)候,設(shè)置Tag值,通過代理將Tag值回傳,再通過TabBar控制器的selectedIndex屬性切換控制器
- (void)tabBarView:(JSTabBarView *)tabBarView withSelectedJSButtonTag:(JSButton *)button;
@end
@interface JSTabBarView : UIView
@property (nonatomic,weak) id <TabBarViewSelectedIndexDelegate> delegate;
/**
* 創(chuàng)建自定義TabBar中Button的圖片
*
* @param imageNormal UIControlStateNormal狀態(tài)下的圖片
* @param imageSel UIControlStateSelected狀態(tài)下的圖片
*/
- (void)creatButtonWithNormalImage:(NSString *)normalImageName andSelectdImage:(NSString *)selectedImageName;
@end
.m文件中
@interface JSTabBarView ()
//JSButton繼承自UIButton,里面只是重寫了setHighlighted:(BOOL)highlighted,去掉系統(tǒng)默認(rèn)提供的樣式(點(diǎn)擊button時(shí)高亮顯示)
@property (nonatomic,strong) JSButton *selectedButton;
@end
@implementation JSTabBarView
- (void)creatButtonWithNormalImage:(NSString *)normalImageName andSelectdImage:(NSString *)selectedImageName{
UIImage *normalImage = [UIImage imageNamed:normalImageName];
UIImage *selectedImage = [UIImage imageNamed:selectedImageName];
JSButton *button = [[JSButton alloc]init];
[button setImage:normalImage forState:UIControlStateNormal];
[button setImage:selectedImage forState:UIControlStateSelected];
[self addSubview:button];
[button addTarget:self action:@selector(buttonClick:) forControlEvents:UIControlEventTouchDown];
}
/**
* 按鈕的點(diǎn)擊事件中主要有兩部分:
* 1.點(diǎn)中當(dāng)前button時(shí)取消上一個(gè)button的選中狀態(tài)
* 2.代理對(duì)象執(zhí)行代理方法
*/
- (void)buttonClick:(JSButton *)sender{
self.selectedButton.selected = NO;
sender.selected = YES;
self.selectedButton = sender;
if ( [self.delegate respondsToSelector:@selector(tabBarView:withSelectedJSButtonTag:)]) {
[self.delegate tabBarView:self withSelectedJSButtonTag:sender];
}
}
- (void)layoutSubviews{
[super layoutSubviews];
CGFloat width = self.bounds.size.width / self.subviews.count;
CGFloat heigth = self.bounds.size.height;
CGFloat buttonY = 0;
for (int i = 0; i < self.subviews.count; i ++) {
CGFloat buttonX = i * width;
JSButton *button = (JSButton *)self.subviews[i];
button.tag = i;
button.frame = CGRectMake(buttonX, buttonY, width, heigth);
if (i == 0) {
[self buttonClick:button];
}
}
}
這樣自定義的TabBar就可以導(dǎo)入使用了,先創(chuàng)建一個(gè)繼承自TabBarController的類,創(chuàng)建一個(gè)自定義的TabBarView,并將TabBarView添加到當(dāng)前自定義TabBarController的tabBar上,for循環(huán)創(chuàng)建自定義TabBar上的button,實(shí)現(xiàn)代理方法切換選中Button對(duì)應(yīng)的控制器
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
/**
* 獲取導(dǎo)航控制器
*/
UINavigationController *hallNavigationController = [self loadStoryBoardWithStoryBoardName:@"Hall"];
UINavigationController *arenalNavigationController = [self loadStoryBoardWithStoryBoardName:@"Arenal"];
UINavigationController *discoveryNavigationController = [self loadStoryBoardWithStoryBoardName:@"Discovery"];
UINavigationController *historyNavigationController = [self loadStoryBoardWithStoryBoardName:@"History"];
UINavigationController *myLotteryNavigationController = [self loadStoryBoardWithStoryBoardName:@"MyLottery"];
//給當(dāng)前的自定義TabBarController設(shè)置子控制器
self.viewControllers = @[hallNavigationController,arenalNavigationController,discoveryNavigationController,historyNavigationController,myLotteryNavigationController];
//創(chuàng)建自定義的TabBarView
JSTabBarView *tabBarView = [[JSTabBarView alloc]init];
//設(shè)置代理對(duì)象
tabBarView.delegate = self;
// tabBarView.frame = self.tabBar.frame;
// [self.view addSubview:tabBarView];//如果按這種方式設(shè)置frame和添加到視圖,當(dāng)push到某一控制器后需要隱藏TabBar時(shí),自定義的TabBarView還存在(所以需要通過設(shè)置bounds,并添加到tabBar上)
//設(shè)置frame
tabBarView.frame = self.tabBar.bounds;
//將自定義的TabBarView添加到當(dāng)前自定義TabBarController的tabBar上(將tabBar覆蓋)
[self.tabBar addSubview:tabBarView];
//for循環(huán)創(chuàng)建自定義TabBarView中的button(根據(jù)子控制器的個(gè)數(shù)創(chuàng)建)
for (int i = 0; i < self.viewControllers.count; i ++) {
[tabBarView creatButtonWithNormalImage:[NSString stringWithFormat:@"TabBar%d",i+1] andSelectdImage:[NSString stringWithFormat:@"TabBar%dSel",i+1]];
}
}
代理方法:
/**
* 自定義TabBarView的代理方法,實(shí)現(xiàn)控制器切換
*
* @param tabBarView 自定義的TabBarView
* @param button 選中的Button
*/
- (void)tabBarView:(JSTabBarView *)tabBarView withSelectedJSButtonTag:(JSButton *)button{
//這里利用TabBarController的selectedIndex屬性通過傳遞的button的tag值來進(jìn)行設(shè)置,實(shí)現(xiàn)控制器的切換
self.selectedIndex = button.tag;
}