UITabBarController自带的标签栏样式太过单一,很多时候都需要我们去自定义标签栏。对于自定义标签栏,比较常见的有两种方法:
、扩展UIViewController,自已用代码构造出一个标签栏控制器,然后定制tabBar。
、隐藏UITabBarController自带的标签栏,自己用UIView定制一个tabBar。
用第1种方法定制,如果想要在性能上和表现上都很接近UITabBarController,难度较大。索性网络上有很多这样的demo。我们只要拿来用就可以了。
本文所要讲解的是用第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];