UITabBarController自帶的標籤欄樣式太過單一,很多時候都需要我們去自定義標籤欄。對於自定義標籤欄,比較常見的有兩種方法:
1、擴展UIViewController,自已用代碼構造出一個標籤欄控制器,然後定製tabBar。
2、隱藏UITabBarController自帶的標籤欄,自己用UIView定製一個tabBar。
用第1種方法定製,如果想要在性能上和表現上都很接近UITabBarController,難度較大。索性網絡上有很多這樣的demo。我們只要拿來用就可以了。例如:http://code4app.com/ios/AKTabBarController/510892996803faf06b000000
本文所要講解的是用第2種方法實現標籤欄定製(源碼)。下圖是工程整體結構:
最爲標準的做法,我們會在工程的AppDelegate文件中實例化標籤欄控制器,然後爲它的viewControllers屬性賦值,接着就着手定製標籤欄。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
self.viewController = [[[UITabBarController alloc] init] autorelease];
FirstViewController *first = [[FirstViewController alloc] initWithNibName:@"FirstViewController" bundle:nil];
SecondViewController *second = [[SecondViewController alloc] initWithNibName:@"SecondViewController" bundle:nil];
ThirdViewController *third = [[ThirdViewController alloc] initWithNibName:@"ThirdViewController" bundle:nil];
FourthViewController *fourth = [[FourthViewController alloc] initWithNibName:@"FourthViewController" bundle:nil];
FifthViewController *fifth = [[FifthViewController alloc] initWithNibName:@"FifthViewController" bundle:nil];
UINavigationController *firstNav = [[UINavigationController alloc] initWithRootViewController:first];
UINavigationController *secondNav = [[UINavigationController alloc] initWithRootViewController:second];
UINavigationController *thirdNav = [[UINavigationController alloc] initWithRootViewController:third];
UINavigationController *fourthNav = [[UINavigationController alloc] initWithRootViewController:fourth];
UINavigationController *fifthNav = [[UINavigationController alloc] initWithRootViewController:fifth];
self.viewController.viewControllers = [NSArray arrayWithObjects:firstNav,secondNav,thirdNav,fourthNav,fifthNav, nil];
[first release];
[second release];
[third release];
[fourth release];
[fifth release];
[firstNav release];
[secondNav release];
[thirdNav release];
[fourthNav release];
[fifthNav release];
/* 自定義標籤欄 */
self.customTabBar = [[[CustomTabBar alloc] init] autorelease];
self.customTabBar.tabBarController = self.viewController;
[self.customTabBar custom];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
上面的代碼中,我們創建了一個有5個標籤的標籤欄控制器,然後我們開始定製它的標籤欄。你會注意到,工程中把所有定製標籤欄的代碼都封裝進了CustomTabBar類。等到需要我們定製的時候,只要實例化CustomTabBar,然後初始化它的tabController屬性,最後調用它的custom:方法就可以實現定製。你也許會問,既然要封裝這些代碼,爲什麼不選擇將它們封裝進UITabBarController的子類中呢?原因是蘋果的官方文檔不提倡我們子類化UITabBarController,考慮到此,故創建了一個繼承自NSObject的類,來封裝自定義標籤欄的所有操作。到時候我們只要簡單地調用一個接口就可以實現自定義標籤欄。是不是很方便呢。下面是CustomTabBar類的實現:
CustomTabBar.h
#import <Foundation/Foundation.h>
@interface CustomTabBar : NSObject
@property (nonatomic,retain) UITabBarController *tabBarController; // 要定製標籤欄的標籤欄控制器,比須先爲它賦值
@property (nonatomic,retain) NSArray *items;
@property (nonatomic,retain) UIImage *tabBarBgImage;
@property (nonatomic,retain) UIView *customTabBar;
@property (nonatomic,assign) NSInteger nowSelected;
@property (nonatomic,assign) NSInteger lastSelected;
- (void)custom; // 自定義標籤欄
- (void)hideRealTabBar; // 隱藏自帶的標籤欄
- (void)configTabBar; // 配置標籤按鈕圖片、標題
- (void)createTabBar; // 創建自定義的tabBar
- (void)tabBarButtonClicked:(id)sender; // 標籤欄按鈕點擊時間回調
@end
CustomTabBar.m
#import "CustomTabBar.h"
#import "YXItem.h"
@implementation CustomTabBar
@synthesize items,tabBarBgImage,customTabBar,nowSelected,lastSelected,tabBarController;
#pragma mark -
#pragma mark Custom TabBar
// 自定義標籤欄
- (void)custom
{
if (tabBarController) {
[self hideRealTabBar]; // 隱藏自帶的標籤欄
[self configTabBar]; // 配置自定義的標籤欄
[self createTabBar]; // 創建自定義的標籤欄
}
else {
NSLog(@"請先爲tabBarController屬性賦值");
}
}
// 隱藏自帶的標籤欄
- (void)hideRealTabBar
{
for(UIView *view in tabBarController.view.subviews){
if([view isKindOfClass:[UITabBar class]]){
view.hidden = YES;
break;
}
}
}
// 配置標籤欄,可以根據實際情況更改配置數據
- (void)configTabBar
{
self.tabBarBgImage = [[UIImage imageNamed:@"tabbar_Bg.png"]resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0) resizingMode:UIImageResizingModeTile];
UIImage *bgImage = [UIImage imageNamed:@"tabBar_BtnBg.png"];
YXItem *item1 = [[YXItem alloc] init];
item1.title = @"star";
item1.iconNormal = [UIImage imageNamed:@"tabBar_icon.png"];
item1.iconSelected = [UIImage imageNamed:@"tabBar_icon.png"];
item1.bgImage = bgImage;
YXItem *item2 = [[YXItem alloc] init];
item2.title = @"star";
item2.iconNormal = [UIImage imageNamed:@"tabBar_icon.png"];
item2.iconSelected = [UIImage imageNamed:@"tabBar_icon.png"];
item2.bgImage = bgImage;
YXItem *item3 = [[YXItem alloc] init];
item3.title = @"star";
item3.iconNormal = [UIImage imageNamed:@"tabBar_icon.png"];
item3.iconSelected = [UIImage imageNamed:@"tabBar_icon.png"];
item3.bgImage = bgImage;
YXItem *item4 = [[YXItem alloc] init];
item4.title = @"star";
item4.iconNormal = [UIImage imageNamed:@"tabBar_icon.png"];
item4.iconSelected = [UIImage imageNamed:@"tabBar_icon.png"];
item4.bgImage = bgImage;
YXItem *item5 = [[YXItem alloc] init];
item5.title = @"star";
item5.iconNormal = [UIImage imageNamed:@"tabBar_icon.png"];
item5.iconSelected = [UIImage imageNamed:@"tabBar_icon.png"];
item5.bgImage = bgImage;
self.items = [NSMutableArray arrayWithObjects:item1, item2, item3, item4, item5, nil];
[item1 release];
[item2 release];
[item3 release];
[item4 release];
[item5 release];
}
// 代碼創建標籤欄
- (void)createTabBar
{
self.customTabBar = [[[UIView alloc] initWithFrame:CGRectMake(0.0f, tabBarController.view.frame.size.height - 49.0f, 320.0f, 49.0f)] autorelease];
UIImageView *bg = [[UIImageView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, self.customTabBar.frame.size.width, self.customTabBar.frame.size.height)];
bg.image = tabBarBgImage;
bg.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
[customTabBar addSubview:bg];
[bg release], bg = nil;
NSInteger num = items.count;
NSInteger buttonWidth = ceil(self.customTabBar.frame.size.width/num);
for (int i = 0; i < num; i ++)
{
float frame_x;
YXItem *item = [items objectAtIndex:i];
frame_x = i * buttonWidth;
if (i == num - 1) {
buttonWidth = self.customTabBar.frame.size.width - frame_x;
}
// 創建button
UIButton *btnItem = [UIButton buttonWithType:UIButtonTypeCustom];
btnItem.frame = CGRectMake(frame_x, 0.0f, buttonWidth, self.customTabBar.frame.size.height);
btnItem.contentEdgeInsets = UIEdgeInsetsMake(8, 17, 13, 17); // 設置icon大小
btnItem.tag = 10000 + i;
[btnItem setImage:item.iconNormal forState:UIControlStateNormal]; // normal
[btnItem setImage:item.iconSelected forState:UIControlStateHighlighted]; // highlighted
[btnItem setImage:item.iconSelected forState:UIControlStateSelected]; // selected
[btnItem setBackgroundImage:item.bgImage forState:UIControlStateSelected];
[btnItem addTarget:self action:@selector(tabBarButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
btnItem.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth;
[customTabBar addSubview:btnItem];
// 創建label
UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(btnItem.center.x - 16.0f, btnItem.center.y + 7.0f, 32.0f, 21.0f)];
titleLabel.text = item.title;
titleLabel.textAlignment = NSTextAlignmentCenter;
titleLabel.font = [UIFont fontWithName:@"STHeitiSC-Light" size:9];
titleLabel.backgroundColor = [UIColor clearColor];
titleLabel.enabled = NO;
titleLabel.userInteractionEnabled = NO;
titleLabel.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth;
[customTabBar addSubview:titleLabel];
[titleLabel release], titleLabel = nil;
// 標籤欄默認選中第一個
if (i == 0) {
btnItem.selected = YES;
nowSelected = 10000 + i;
lastSelected = 10000 + i;
}
}
customTabBar.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleBottomMargin;
[tabBarController.view addSubview:customTabBar];
[tabBarController.view bringSubviewToFront:customTabBar];
}
// 按鈕點擊回調
- (void)tabBarButtonClicked:(id)sender
{
UIButton *button = (UIButton *)sender;
// 如果當前tab不是被選中的
if (!button.selected) {
lastSelected = nowSelected;
nowSelected = button.tag;
[button setSelected:YES]; // 設定爲選中狀態
[self.tabBarController setSelectedIndex:nowSelected - 10000];
UIButton *lastBtn = (UIButton *)[customTabBar viewWithTag:lastSelected];
[lastBtn setSelected:NO];
}
else {
// do nothing
}
}
#pragma mark -
- (void)dealloc
{
[tabBarController release], tabBarController = nil;
[items release], items = nil;
[tabBarBgImage release], tabBarBgImage = nil;
[customTabBar release], customTabBar = nil;
[super dealloc];
}
@end
#import <Foundation/Foundation.h>
@interface YXItem : NSObject
@property (nonatomic,copy) NSString *title; // 按鈕的標題
@property (nonatomic,retain) UIImage *iconNormal; // 一般狀態下的icon
@property (nonatomic,retain) UIImage *iconSelected; // 選中或高亮狀態下的icon
@property (nonatomic,retain) UIImage *bgImage; // 按鈕的背景
@end
最終實現的效果如下:
1、像往常一樣,在application: didFinishLaunchingWithOptions:創建UITabBarController作爲整個App的根。
2、將YXItem.h\YXItem.m、CustomTabBar.h\CustomTabBar.m拉入你的工程中。
3、在configTabBar:方法中配置數據,主要是按鈕的一些icon、背景圖等。
4、在application: didFinishLaunchingWithOptions:中適當的位置添加如下代碼,實現定製。
/* 自定義標籤欄 */
self.customTabBar = [[[CustomTabBar alloc] init] autorelease];
self.customTabBar.tabBarController = self.viewController;
[self.customTabBar custom];