`
jishublog
  • 浏览: 865864 次
文章分类
社区版块
存档分类
最新评论

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


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics