作為iOS開發最常用的兩個多視圖控制器 NavigationController 和 TabBarController 已經很強大了,基本上在大部分的應用中都能看到它們的影子。但是在使用的過程中,系統自帶的空間也經常不能滿足我們的需求,所以經常需要使用自定義來實現功能。
之前寫過自定義NavigationBar: http://www.cnblogs.com/code-cd/p/4801661.html 。今天大概寫一下自定義TabBar。如有不足之處,還請多多指正。
一、創建TabBarContoller
創建 CDTabBarController,CDRedViewController,CDGreenViewController

在AppDelegate.m中,設置創建TabBarController,並設置根視圖為TabBarController
//
// AppDelegate.m
// ComstomTabBar
//
// Created by lcd on 15/9/15.
// Copyright © 2015年 lcd. All rights reserved.
//
#import "AppDelegate.h"
#import "CDTabBarController.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
CDTabBarController *tabBarController = [[CDTabBarController alloc] init];
self.window.rootViewController = tabBarController;
return YES;
}
添加子視圖
在CDTabBarController.m中
//
// CDTabBarController.m
// ComstomTabBar
//
// Created by lcd on 15/9/15.
// Copyright © 2015年 lcd. All rights reserved.
//
#import "CDTabBarController.h"
#import "CDRedViewController.h"
#import "CDGreenViewController.h"
@interface CDTabBarController ()
@end
@implementation CDTabBarController
- (void)viewDidLoad {
[super viewDidLoad];
//設置子視圖
[self setupChildControllers];
}
//這里設置兩個視圖控制器的代碼是重復的,為了便於觀察理解,我沒有抽取,大家日常寫代碼的時候請注意養成良好的代碼習慣。
- (void)setupChildControllers {
CDRedViewController *redViewController = [[CDRedViewController alloc] init];
redViewController.view.backgroundColor = [UIColor redColor];
redViewController.tabBarItem.title = @"red";
//設置圖片
redViewController.tabBarItem.image = [UIImage imageNamed:@"tabbar_mainframe"];
//設置選中圖片
redViewController.tabBarItem.selectedImage = [UIImage imageNamed:@"tabbar_mainframeHL"];
CDGreenViewController *greenViewController = [[CDGreenViewController alloc] init];
greenViewController.view.backgroundColor = [UIColor greenColor];
greenViewController.tabBarItem.title = @"green";
greenViewController.tabBarItem.image = [UIImage imageNamed:@"tabbar_me"];
greenViewController.tabBarItem.selectedImage = [UIImage imageNamed:@"tabbar_meHL"];
self.viewControllers = @[redViewController,greenViewController];
}
這樣兩個子視圖已經添加進TabBarViewController了。如圖:

但是這里有個問題。,我設置的選中圖片 是綠色的,這里顯示的卻是藍色的。
這是因為在ios7之后,蘋果默認會把UITabBar上面的按鈕圖片渲染成藍色。如果要顯示自己需要的顏色可以通過以下方法:
UIImage *selectedImage = [[UIImage imageNamed:@"tabbar_mainframeHL"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
redViewController.tabBarItem.selectedImage = selectedImage;
二、自定義TabBar
自定義TabBar有幾種不同的方式,難易程度不同,效果也不盡相同
1.修改TabBar字體
方法1:
在CDRedViewController.m中
NSDictionary *dic = @{NSFontAttributeName:[UIFont systemFontOfSize:11.0],
NSBackgroundColorAttributeName:[UIColor cyanColor]};
[self.tabBarItem setTitleTextAttributes:dic forState:UIControlStateNormal];
方法二:
在CDTabBarController.m中
- (instancetype)init
{
self = [super init];
if (self) {
[self setTabBarItem:self.tabBarItem Title:@"title" withTitleSize:17.0 andFoneName:@"Marion-Italic" selectedImage:selectedImage withTitleColor:[UIColor redColor] unselectedImage:unselectedImage withTitleColor:[UIColor blueColor]];
}
return self;
}
- (void)setTabBarItem:(UITabBarItem *)tabbarItem
Title:(NSString *)title
withTitleSize:(CGFloat)size
andFoneName:(NSString *)foneName
selectedImage:(NSString *)selectedImage
withTitleColor:(UIColor *)selectColor
unselectedImage:(NSString *)unselectedImage
withTitleColor:(UIColor *)unselectColor{
//設置圖片
tabbarItem = [tabbarItem initWithTitle:title image:[[UIImage imageNamed:unselectedImage]imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] selectedImage:[[UIImage imageNamed:selectedImage]imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]];
//未選中字體顏色
[[UITabBarItem appearance] setTitleTextAttributes:@{NSForegroundColorAttributeName:unselectColor,NSFontAttributeName:[UIFont fontWithName:foneName size:size]} forState:UIControlStateNormal];
//選中字體顏色
[[UITabBarItem appearance] setTitleTextAttributes:@{NSForegroundColorAttributeName:selectColor,NSFontAttributeName:[UIFont fontWithName:foneName size:size]} forState:UIControlStateSelected];
}
這種方法可以修改TabBar字體大小。但是其本質還是系統自帶的TabBar。離我們的目標:真正的自定義TabBar還有距離
2.這種方法是之前查到的一種,用過一次,感覺不是很好用,貼上代碼,有興趣的可以了解一下,沒興趣的建議直接看第三種
- (UIButton *)plusButton
{
if (_plusButton == nil) {
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
[btn setImage:[UIImage imageNamed:@"tabbar_compose_icon_add"] forState:UIControlStateNormal];
[btn setImage:[UIImage imageNamed:@"tabbar_compose_background_icon_add"] forState:UIControlStateHighlighted];
[btn setBackgroundImage:[UIImage imageNamed:@"tabbar_compose_button"] forState:UIControlStateNormal];
[btn setBackgroundImage:[UIImage imageNamed:@"tabbar_compose_button_highlighted"] forState:UIControlStateHighlighted];
// 默認按鈕的尺寸跟背景圖片一樣大
// sizeToFit:默認會根據按鈕的背景圖片或者image和文字計算出按鈕的最合適的尺寸
[btn sizeToFit];
_plusButton = btn;
[self addSubview:_plusButton];
}
return _plusButton;
}
// self.items UITabBarItem模型,有多少個子控制器就有多少個UITabBarItem模型
// 調整子控件的位置
- (void)layoutSubviews
{
[super layoutSubviews];
CGFloat w = self.bounds.size.width;
CGFloat h = self.bounds.size.height;
CGFloat btnX = 0;
CGFloat btnY = 0;
CGFloat btnW = w / (self.items.count + 1);
CGFloat btnH = self.bounds.size.height;
int i = 0;
// 調整系統自帶的tabBar上的按鈕位置
for (UIView *tabBarButton in self.subviews) {
// 判斷下是否是UITabBarButton
if ([tabBarButton isKindOfClass:NSClassFromString(@"UITabBarButton" )]) {
if (i == 2) {
i = 3;
}
btnX = i * btnW;
tabBarButton.frame = CGRectMake(btnX, btnY, btnW, btnH);
i++;
}
}
// 設置添加按鈕的位置
self.plusButton.center = CGPointMake(w * 0.5, h * 0.5);
}
3.這種方法的思路是,先把自帶的TabBar取消,然后自定義View,add到TabBar的位置代替TabBar。然后在自定義View上添加button,設置button點擊時間,改變selectIndex,關聯各個子viewController,覆蓋相關事件。
//注釋掉[super setHighlighted:highlighted] 即可以取消點擊時的高亮狀態
- (void)setHighlighted:(BOOL)highlighted{
// [super setHighlighted:highlighted];
}
CDTabBarController.h
// // CDTabBarController.h // ComstomTabBar // // Created by lcd on 15/9/15. // Copyright © 2015年 lcd. All rights reserved. // #import <UIKit/UIKit.h> @interface CDTabBarController : UITabBarController @end
CDTabBarController.m
//
// CDTabBarController.m
// ComstomTabBar
//
// Created by lcd on 15/9/15.
// Copyright © 2015年 lcd. All rights reserved.
//
#import "CDTabBarController.h"
#import "CDRedViewController.h"
#import "CDGreenViewController.h"
#import "CDTabBarButton.h"
@interface CDTabBarController ()
/**
* 設置之前選中的按鈕
*/
@property (nonatomic, weak) UIButton *selectedBtn;
@end
@implementation CDTabBarController
- (void)viewDidLoad {
[super viewDidLoad];
//設置子視圖
[self setupChildControllers];
//設置TabBar
[self setupTabBar];
}
- (void)setupChildControllers {
CDRedViewController *redViewController = [[CDRedViewController alloc] init];
redViewController.view.backgroundColor = [UIColor redColor];
redViewController.tabBarItem.title = @"red";
//設置圖片
redViewController.tabBarItem.image = [UIImage imageNamed:@"tabbar_mainframe"];
//設置選中圖片
redViewController.tabBarItem.selectedImage = [UIImage imageNamed:@"tabbar_mainframeHL"];
CDGreenViewController *greenViewController = [[CDGreenViewController alloc] init];
greenViewController.view.backgroundColor = [UIColor greenColor];
greenViewController.tabBarItem.title = @"green";
greenViewController.tabBarItem.image = [UIImage imageNamed:@"tabbar_me"];
greenViewController.tabBarItem.selectedImage = [UIImage imageNamed:@"tabbar_meHL"];
self.viewControllers = @[redViewController,greenViewController];
}
- (void)setupTabBar {
//刪除現有的tabBar
CGRect rect = self.tabBar.frame;
[self.tabBar removeFromSuperview]; //移除TabBarController自帶的下部的條
UIView *myView = [[UIView alloc] init];
myView.frame = rect;
myView.backgroundColor = [UIColor cyanColor];
[self.view addSubview:myView];
for (int i = 0; i < 2; i++) {
CDTabBarButton *button = [[CDTabBarButton alloc] init];
NSString *imageName = [NSString stringWithFormat:@"tabbar_%d",i];
NSString *imageNameSel = [NSString stringWithFormat:@"tabbar_%dHL",i];
[button setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];
[button setImage:[UIImage imageNamed:imageNameSel] forState:UIControlStateSelected];
CGFloat x = i * myView.frame.size.width / 2;
button.frame = CGRectMake(x, 0, myView.frame.size.width / 2, myView.frame.size.height);
[myView addSubview:button];
//設置按鈕的標記, 方便來索引當前的按鈕,並跳轉到相應的視圖
button.tag = i;
[button addTarget:self action:@selector(clickBtn:) forControlEvents:UIControlEventTouchUpInside];
//設置初始顯示界面
if (0 == i) {
button.selected = YES;
self.selectedBtn = button; //設置該按鈕為選中的按鈕
}
}
}
//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
效果如圖所示

這種方法是用UIView替代TabBar,自定義性強,可以在view上添加自己想要的各種控件,實現動畫效果等。
PSL:本文所牽涉代碼,只為提供一個思路,為方便新入門iOS開發者觀看,均未抽取,重構,很多東西待優化。大家日常寫代碼的時候記得養成良好習慣就好。
