UITabBarController自定义标签栏

来源:互联网 发布:tomcat端口怎么看 编辑:程序博客网 时间:2024/05/23 18:32

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