UITabBarController自定義標籤欄

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
configTabBar:方法配置自定義的數據。然後createTabBar:將調用這些數據進行標籤欄定製。爲了方便數據的調用和管理,我們還創建了一個數據模型YXItem,它的頭文件如下:

#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];


發佈了28 篇原創文章 · 獲贊 0 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章