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