搞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方法(这问题可以修改,不过目前懒得动了),另外没经过实际项目测试等等。。。