搞IOS开发的都知道,系统自带的UITabBar功能有限,默认的就是切换页面,那种弹出菜单啥的都不支持,而且可控制程度很低,样式修改也麻烦等等一堆问题。在经历了公司第一个项目那抹布一样的界面之后,决定将各组件全自定义一遍,不说多么花哨,但至少要看着顺眼。OK 开工
首先自定义一个控制器类 MyTabBarController,代码如下(包含了注释,将就看吧):
// // MyTabBarViewController.h // newIosMobile // // Created by xoHome on 13-1-31. // Copyright (c) 2013年 xoHome. All rights reserved. // #import <UIKit/UIKit.h> #import "MyTabBar.h" #import "MyTabBarItem.h" #define MyTabBarStyle int #define MyTabBarStyleViewController 1 #define MyTabBarStyleClick 2 @interface MyTabBarController : UIViewController { // UITabBar View MyTabBar *tabBar; // MainView, 包含BodyView和其它追加View UIView *mainView; // Body View UIView *bodyView; // UIViewController集合 NSMutableArray *viewControllers; // 当前显示UIViewController下标 int selectedIndex; // 显示最大元素 int maxItems; // 回调delegate id delegate; } @property(nonatomic, readonly) MyTabBar *tabBar; @property(nonatomic, readonly) UIView *mainView; @property(nonatomic) int selectedIndex; @property(nonatomic, retain) id delegate; // 根据类型添加视图,viewControllers集合为存放容器 // tabBar数量最大值为maxItems - (void) addViewController:(UIViewController *)controller resource:(MyTabBarItem *)resource; // 添加非Controller视图 - (void) addEventTabItem:(MyTabBarItem *)resource; // 添加完成,执行绘制 - (void) addDone; // 返回指定下标TabBar样式 - (MyTabBarStyle) tabBarStyle:(int)index; // 选择事件处理 - (void) didSelectItem:(id)sender; @end @protocol MyTabBarControllerDelegate <NSObject> @optional - (void) myTabBarController:(MyTabBarController *)tabBarController didSelectViewController:(id)viewController index:(int)index; @end对应m文件为:
// // MyTabBarViewController.m // newIosMobile // 自定义UITabBar // Created by xoHome on 13-1-31. // Copyright (c) 2013年 xoHome. All rights reserved. // #import "MyTabBarController.h" @interface MyTabBarController () @end @implementation MyTabBarController @synthesize tabBar; @synthesize mainView; @synthesize selectedIndex; @synthesize delegate; - (id) init { self = [super init]; selectedIndex = -1; maxItems = 5; viewControllers = [[NSMutableArray alloc] initWithCapacity:maxItems]; self.view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]]; tabBar = [[MyTabBar alloc] initWithFrame:CGRectMake(0, self.view.frame.size.height - 49, self.view.frame.size.width, 49)]; tabBar.controller = self; mainView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height - 49)]; [self.view addSubview:mainView]; bodyView = [[UIView alloc] initWithFrame:mainView.frame]; [mainView addSubview:bodyView]; [self.view addSubview:tabBar]; return self; } - (void) addDone { // 生成UI NSMutableArray *items = [[NSMutableArray alloc] initWithCapacity:viewControllers.count]; for(NSDictionary *item in viewControllers) { [items addObject:[item objectForKey:@"resource"]]; } [tabBar addTabItems:items]; [items release]; // 默认显示第一项 for(int i=0; i<viewControllers.count; i++) { if([[[viewControllers objectAtIndex:i] objectForKey:@"style"] intValue] == MyTabBarStyleViewController) { [self didSelectItemByIndex:i]; break; } } } - (void) addViewController:(UIViewController *)controller resource:(MyTabBarItem *)resource{ if(viewControllers.count >= maxItems) { // 包含Controller数量达到规定maxItems则不操作 return; } [self addItem:controller resource:resource style:MyTabBarStyleViewController]; } - (void) addEventTabItem:(MyTabBarItem *)resource { [self addItem:nil resource:resource style:MyTabBarStyleClick]; } // 添加视图公共方法 - (void) addItem:(id)item resource:(MyTabBarItem *)resource style:(MyTabBarStyle)style { id temp = item == nil ? [NSNull null] : item; NSDictionary *tabItem = [NSDictionary dictionaryWithObjectsAndKeys:temp, @"controller", [NSNumber numberWithInt:style], @"style", resource, @"resource", nil]; [viewControllers addObject:tabItem]; } - (MyTabBarStyle) tabBarStyle:(int)index { if(index >= viewControllers.count) { return -1; } return [[[viewControllers objectAtIndex:index] objectForKey:@"style"] intValue]; } - (void) didSelectItem:(id)sender { int index = [sender tag]; [self didSelectItemByIndex:index]; } - (void) didSelectItemByIndex:(int)index { MyTabBarStyle style = [self tabBarStyle:index]; if(style == MyTabBarStyleViewController) { [tabBar didSelectItem:index]; if(selectedIndex == index) { return; } if(selectedIndex > -1) { [[[[viewControllers objectAtIndex:selectedIndex] objectForKey:@"controller"] view] removeFromSuperview]; } UIView *temp = [[[viewControllers objectAtIndex:index] objectForKey:@"controller"] view]; temp.frame = bodyView.frame; [bodyView addSubview:temp]; selectedIndex = index; } // 回调delegate if([delegate respondsToSelector:@selector(myTabBarController:didSelectViewController:index:)]) { [delegate myTabBarController:self didSelectViewController:[[viewControllers objectAtIndex:selectedIndex]objectForKey:@"controller"] index:index]; } } - (void) dealloc { [super dealloc]; [tabBar release]; [mainView release]; [bodyView release]; [viewControllers release]; [delegate release]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; } @end
UI组件MyTabBar文件如下:
// // MyTabBar.h // newIosMobile // // Created by xoHome on 13-1-31. // Copyright (c) 2013年 xoHome. All rights reserved. // #import <UIKit/UIKit.h> @interface MyTabBar : UIView { // Background View UIImageView *backgroundView; // TabItem控件集合 NSMutableArray *tabItems; // resource集合 NSArray *resources; // delegate id controller; } @property(nonatomic, retain)id controller; @property(nonatomic, readonly)UIImageView *backgroundView; // 添加TabItems - (void) addTabItems:(NSArray *)items; - (void) didSelectItem:(int)index; @end
// // MyTabBar.m // newIosMobile // // Created by xoHome on 13-1-31. // Copyright (c) 2013年 xoHome. All rights reserved. // #import "MyTabBar.h" #import "MyTabBarController.h" #import "MyTabBarItemView.h" @implementation MyTabBar @synthesize controller; @synthesize backgroundView; - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; backgroundView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)]; [backgroundView setBackgroundColor:[UIColor blackColor]]; [self addSubview:backgroundView]; tabItems = [[NSMutableArray alloc] initWithCapacity:5]; return self; } - (void) addTabItems:(NSArray *)items { resources = [items retain]; float width = self.frame.size.width / resources.count; int index = 0; for(MyTabBarItem *item in resources) { /* UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom]; btn.showsTouchWhenHighlighted = YES; btn.tag = index; btn.frame = CGRectMake(width * index, 0, width, self.frame.size.height); [btn.titleLabel setFont:[UIFont systemFontOfSize:13]]; [btn setImage:item.iDefault forState:UIControlStateNormal]; [btn setImage:item.iHighlighted forState:UIControlStateHighlighted]; [btn setImage:item.iSeleted forState:UIControlStateSelected]; NSLog(@"%f", btn.imageView.frame.size.width); [btn setTitle:item.text forState:UIControlStateNormal]; [btn addTarget:controller action:@selector(didSelectItem:) forControlEvents:UIControlEventTouchUpInside]; [tabItems addObject:btn]; [self addSubview:btn];*/ MyTabBarItemView *btn = [[MyTabBarItemView alloc] initWithImage:item.iDefault text:item.text frame:CGRectMake(width * index, 0, width, self.frame.size.height) deletage:controller]; btn.button.tag = index; [tabItems addObject:btn]; [self addSubview:btn]; [btn release]; index ++; } } - (void) dealloc { [super dealloc]; [backgroundView release]; [tabItems release]; [controller release]; [resources release]; } - (void) didSelectItem:(int)index { for (int i = 0; i < tabItems.count; i++) { MyTabBarItemView *btn = [tabItems objectAtIndex:i]; MyTabBarItem *item = [resources objectAtIndex:i]; if(i != index) { [btn.imageView setImage:item.iDefault]; btn.userInteractionEnabled = YES; [btn setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:@"bg.png"]]]; } else { [btn.imageView setImage:item.iHighlighted]; btn.userInteractionEnabled = NO; [btn setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:@"selectedbg.png"]]]; } } } @end对于UIBarItem元素,我本来是打算用UIButton组件的,但UIButton对图片的控制不方便(比如大小位置等),所以自定义了一个 MyTabBarItemView
// // MyTabBarItemView.h // newIosMobile // // Created by xoHome on 13-2-1. // Copyright (c) 2013年 xoHome. All rights reserved. // #import <UIKit/UIKit.h> @interface MyTabBarItemView : UIView { // 按钮 UIButton *button; // 图片 UIImageView *imageView; // 文字 UILabel *txt; } @property(nonatomic, readonly) UIImageView *imageView; @property(nonatomic, readonly) UILabel *txt; @property(nonatomic, readonly) UIButton *button; - (id) initWithImage:(UIImage *)image text:(NSString *)text frame:(CGRect)frame deletage:(id)delegate; @end
// // MyTabBarItemView.m // newIosMobile // // Created by xoHome on 13-2-1. // Copyright (c) 2013年 xoHome. All rights reserved. // #import "MyTabBarItemView.h" @implementation MyTabBarItemView @synthesize imageView; @synthesize txt; @synthesize button; - (id) initWithImage:(UIImage *)image text:(NSString *)text frame:(CGRect)frame deletage:(id)delegate { self = [super initWithFrame:frame]; [self setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:@"bg.png"]]]; imageView = [[UIImageView alloc] initWithFrame:CGRectMake(frame.size.width/2-15, 7, 30, frame.size.height-25)]; [imageView setImage:image]; [self addSubview:imageView]; UIFont *font = [UIFont systemFontOfSize:12]; txt = [[UILabel alloc] initWithFrame:CGRectMake(frame.size.width/2-[text sizeWithFont:font].width/2, frame.size.height - 16, [text sizeWithFont:font].width, 15)]; [txt setFont:[UIFont systemFontOfSize:12]]; [txt setBackgroundColor:[UIColor clearColor]]; [txt setTextColor:[UIColor whiteColor]]; [txt setText:text]; [self addSubview:txt]; button = [UIButton buttonWithType:UIButtonTypeCustom]; button.frame = CGRectMake(0, 0, frame.size.width, frame.size.height); [button setBackgroundColor:[UIColor clearColor]]; button.showsTouchWhenHighlighted = YES; [button addTarget:delegate action:@selector(didSelectItem:) forControlEvents:UIControlEventTouchUpInside]; [self addSubview:button]; return self; } - (void) dealloc { [super dealloc]; [button release]; [imageView release]; [txt release]; } @end基本组件代码就是如上所述的,调用代码如下:
// // ViewController.m // newIosMobile // // Created by xoHome on 13-1-31. // Copyright (c) 2013年 xoHome. All rights reserved. // #import "ViewController.h" #import "IndexViewController.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; tabbar = [[MyTabBarController alloc] init]; [tabbar.view setFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)]; tabbar.delegate = self; //tabbar.tabBar.backgroundView.image = [UIImage imageNamed:@"Table_Bar.png"]; IndexViewController *one = [[IndexViewController alloc] init]; [one.view setBackgroundColor:[UIColor redColor]]; IndexViewController *two = [[IndexViewController alloc] init]; [two.view setBackgroundColor:[UIColor blueColor]]; IndexViewController *three = [[IndexViewController alloc] init]; [three.view setBackgroundColor:[UIColor yellowColor]]; [tabbar addViewController:one resource:MyTabBarItemMake([UIImage imageNamed:@"xianhuo.png"], [UIImage imageNamed:@"xianhuo_click.png"], [UIImage imageNamed:@"xianhuo_click.png"], @"现货")]; [tabbar addViewController:two resource:MyTabBarItemMake([UIImage imageNamed:@"zixun.png"], [UIImage imageNamed:@"zixun_click.png"], [UIImage imageNamed:@"zixun_click.png"], @"资讯")]; [tabbar addViewController:three resource:MyTabBarItemMake([UIImage imageNamed:@"qihuo.png"], [UIImage imageNamed:@"qihuo_click.png"], [UIImage imageNamed:@"qihuo_click.png"], @"期货")]; [tabbar addEventTabItem:MyTabBarItemMake([UIImage imageNamed:@"more.png"], [UIImage imageNamed:@"more_click.png"], nil, @"更多")]; [tabbar addDone]; [self.view addSubview:tabbar.view]; } // MyTabBarController的回调方法 - (void) myTabBarController:(MyTabBarController *)tabBarController didSelectViewController:(id)viewController index:(int)index { if(index == 3) { if(toolView == nil) { toolView = [[UIView alloc] initWithFrame:CGRectMake(0, tabbar.mainView.frame.size.height, tabbar.mainView.frame.size.width, 100)]; [toolView setBackgroundColor:[UIColor scrollViewTexturedBackgroundColor]]; [tabbar.mainView addSubview:toolView]; [toolView setAlpha:0]; } [UIView beginAnimations:nil context:nil]; if(toolView.frame.origin.y >= tabbar.mainView.frame.size.height) { [toolView setAlpha:1]; toolView.frame = CGRectMake(0, tabbar.mainView.frame.size.height - 100, tabbar.mainView.frame.size.width, 100); } else { [toolView setAlpha:0]; toolView.frame = CGRectMake(0, tabbar.mainView.frame.size.height, tabbar.mainView.frame.size.width, 100); } [UIView commitAnimations]; } } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (void) dealloc { [super dealloc]; [tabbar release]; [toolView release]; } @end
给个预览图看看(因为素材不是很高清,所以有点模糊,这个换图片就可以了):
前三项为普通的页面切换,最后一项为自定义功能的选项,主要处理代码写在MyTabBarController的protocol回调方法中。
目前该组件还有些问题,比如:为了调用方便,为了一个个添加UIViewController而不是像系统自带的一次性添加一个数组,最后必须调用addDone方法(这问题可以修改,不过目前懒得动了),另外没经过实际项目测试等等。。。