搞IOS开发的都知道,系统自带的UITabBar功能有限,默认的就是切换页面,那种弹出菜单啥的都不支持,而且可控制程度很低,样式修改也麻烦等等一堆问题。在经历了公司第一个项目那抹布一样的界面之后,决定将各组件全自定义一遍,不说多么花哨,但至少要看着顺眼。OK 开工
首先自定义一个控制器类 MyTabBarController,代码如下(包含了注释,将就看吧):
09 |
#import
<UIKit/UIKit.h> |
11 |
#import
"MyTabBarItem.h" |
13 |
#define
MyTabBarStyle int |
14 |
#define
MyTabBarStyleViewController 1 |
15 |
#define
MyTabBarStyleClick 2 |
17 |
@interface
MyTabBarController : UIViewController { |
26 |
NSMutableArray
*viewControllers; |
38 |
@property(nonatomic,
readonly) MyTabBar *tabBar; |
39 |
@property(nonatomic,
readonly) UIView *mainView; |
40 |
@property(nonatomic) int selectedIndex; |
41 |
@property(nonatomic,
retain) id delegate; |
45 |
-
( void )
addViewController:(UIViewController *)controller resource:(MyTabBarItem *)resource; |
48 |
-
( void )
addEventTabItem:(MyTabBarItem *)resource; |
54 |
-
(MyTabBarStyle) tabBarStyle:( int )index; |
57 |
-
( void )
didSelectItem:(id)sender; |
61 |
@protocol
MyTabBarControllerDelegate <NSObject> |
63 |
-
( void )
myTabBarController:(MyTabBarController *)tabBarController didSelectViewController:(id)viewController index:( int )index; |
对应m文件为:
009 |
#import
"MyTabBarController.h" |
011 |
@interface
MyTabBarController () |
015 |
@implementation
MyTabBarController |
018 |
@synthesize
mainView; |
019 |
@synthesize
selectedIndex; |
020 |
@synthesize
delegate; |
027 |
viewControllers
= [[NSMutableArray alloc] initWithCapacity:maxItems]; |
029 |
self.view
= [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]]; |
031 |
tabBar
= [[MyTabBar alloc] initWithFrame:CGRectMake(0, self.view.frame.size.height - 49, self.view.frame.size.width, 49)]; |
032 |
tabBar.controller
= self; |
034 |
mainView
= [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height - 49)]; |
035 |
[self.view
addSubview:mainView]; |
037 |
bodyView
= [[UIView alloc] initWithFrame:mainView.frame]; |
038 |
[mainView
addSubview:bodyView]; |
040 |
[self.view
addSubview:tabBar]; |
047 |
NSMutableArray
*items = [[NSMutableArray alloc] initWithCapacity:viewControllers.count]; |
048 |
for (NSDictionary
*item in viewControllers) { |
049 |
[items
addObject:[item objectForKey:@ "resource" ]]; |
051 |
[tabBar
addTabItems:items]; |
055 |
for ( int i=0;
i<viewControllers.count; i++) { |
056 |
if ([[[viewControllers
objectAtIndex:i] objectForKey:@ "style" ]
intValue] == MyTabBarStyleViewController) { |
057 |
[self
didSelectItemByIndex:i]; |
063 |
-
( void )
addViewController:(UIViewController *)controller resource:(MyTabBarItem *)resource{ |
064 |
if (viewControllers.count
>= maxItems) { |
068 |
[self
addItem:controller resource:resource style:MyTabBarStyleViewController]; |
071 |
-
( void )
addEventTabItem:(MyTabBarItem *)resource { |
072 |
[self
addItem:nil resource:resource style:MyTabBarStyleClick]; |
076 |
-
( void )
addItem:(id)item resource:(MyTabBarItem *)resource style:(MyTabBarStyle)style { |
077 |
id
temp = item == nil ? [NSNull null] : item; |
078 |
NSDictionary
*tabItem = [NSDictionary dictionaryWithObjectsAndKeys:temp, @ "controller" ,
[NSNumber numberWithInt:style], @ "style" ,
resource, @ "resource" ,
nil]; |
079 |
[viewControllers
addObject:tabItem]; |
082 |
-
(MyTabBarStyle) tabBarStyle:( int )index
{ |
083 |
if (index
>= viewControllers.count) { |
086 |
return [[[viewControllers
objectAtIndex:index] objectForKey:@ "style" ]
intValue]; |
089 |
-
( void )
didSelectItem:(id)sender { |
090 |
int index
= [sender tag]; |
091 |
[self
didSelectItemByIndex:index]; |
094 |
-
( void )
didSelectItemByIndex:( int )index
{ |
095 |
MyTabBarStyle
style = [self tabBarStyle:index]; |
096 |
if (style
== MyTabBarStyleViewController) { |
097 |
[tabBar
didSelectItem:index]; |
098 |
if (selectedIndex
== index) { |
101 |
if (selectedIndex
> -1) { |
102 |
[[[[viewControllers
objectAtIndex:selectedIndex] objectForKey:@ "controller" ]
view] removeFromSuperview]; |
104 |
UIView
*temp = [[[viewControllers objectAtIndex:index] objectForKey:@ "controller" ]
view]; |
105 |
temp.frame
= bodyView.frame; |
106 |
[bodyView
addSubview:temp]; |
107 |
selectedIndex
= index; |
110 |
if ([delegate
respondsToSelector:@selector(myTabBarController:didSelectViewController:index:)]) { |
111 |
[delegate
myTabBarController:self didSelectViewController:[[viewControllers objectAtIndex:selectedIndex]objectForKey:@ "controller" ]
index:index]; |
120 |
[viewControllers
release]; |
124 |
-
( void )didReceiveMemoryWarning |
126 |
[super
didReceiveMemoryWarning]; |
UI组件MyTabBar文件如下:
09 |
#import
<UIKit/UIKit.h> |
11 |
@interface
MyTabBar : UIView { |
13 |
UIImageView
*backgroundView; |
16 |
NSMutableArray
*tabItems; |
24 |
@property(nonatomic,
retain)id controller; |
25 |
@property(nonatomic,
readonly)UIImageView *backgroundView; |
28 |
-
( void )
addTabItems:(NSArray *)items; |
30 |
-
( void )
didSelectItem:( int )index; |
10 |
#import
"MyTabBarController.h" |
11 |
#import
"MyTabBarItemView.h" |
13 |
@implementation
MyTabBar |
15 |
@synthesize
controller; |
16 |
@synthesize
backgroundView; |
18 |
-
(id)initWithFrame:(CGRect)frame |
20 |
self
= [super initWithFrame:frame]; |
22 |
backgroundView
= [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)]; |
23 |
[backgroundView
setBackgroundColor:[UIColor blackColor]]; |
24 |
[self
addSubview:backgroundView]; |
26 |
tabItems
= [[NSMutableArray alloc] initWithCapacity:5]; |
31 |
-
( void )
addTabItems:(NSArray *)items { |
32 |
resources
= [items retain]; |
33 |
float width
= self.frame.size.width / resources.count; |
35 |
for (MyTabBarItem
*item in resources) { |
54 |
MyTabBarItemView
*btn = [[MyTabBarItemView alloc] initWithImage:item.iDefault text:item.text frame:CGRectMake(width * index, 0, width, self.frame.size.height) deletage:controller]; |
55 |
btn.button.tag
= index; |
56 |
[tabItems
addObject:btn]; |
57 |
[self
addSubview:btn]; |
65 |
[backgroundView
release]; |
71 |
-
( void )
didSelectItem:( int )index
{ |
72 |
for ( int i
= 0; i < tabItems.count; i++) |
74 |
MyTabBarItemView
*btn = [tabItems objectAtIndex:i]; |
75 |
MyTabBarItem
*item = [resources objectAtIndex:i]; |
77 |
[btn.imageView
setImage:item.iDefault]; |
78 |
btn.userInteractionEnabled
= YES; |
79 |
[btn
setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:@ "bg.png" ]]]; |
81 |
[btn.imageView
setImage:item.iHighlighted]; |
82 |
btn.userInteractionEnabled
= NO; |
83 |
[btn
setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:@ "selectedbg.png" ]]]; |
对于UIBarItem元素,我本来是打算用UIButton组件的,但UIButton对图片的控制不方便(比如大小位置等),所以自定义了一个 MyTabBarItemView
09 |
#import
<UIKit/UIKit.h> |
11 |
@interface
MyTabBarItemView : UIView { |
16 |
UIImageView
*imageView; |
22 |
@property(nonatomic,
readonly) UIImageView *imageView; |
23 |
@property(nonatomic,
readonly) UILabel *txt; |
24 |
@property(nonatomic,
readonly) UIButton *button; |
26 |
-
(id) initWithImage:(UIImage *)image text:(NSString *)text frame:(CGRect)frame deletage:(id)delegate; |
09 |
#import
"MyTabBarItemView.h" |
11 |
@implementation
MyTabBarItemView |
13 |
@synthesize
imageView; |
17 |
-
(id) initWithImage:(UIImage *)image text:(NSString *)text frame:(CGRect)frame deletage:(id)delegate { |
18 |
self
= [super initWithFrame:frame]; |
20 |
[self
setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:@ "bg.png" ]]]; |
22 |
imageView
= [[UIImageView alloc] initWithFrame:CGRectMake(frame.size.width/2-15, 7, 30, frame.size.height-25)]; |
23 |
[imageView
setImage:image]; |
24 |
[self
addSubview:imageView]; |
26 |
UIFont
*font = [UIFont systemFontOfSize:12]; |
27 |
txt
= [[UILabel alloc] initWithFrame:CGRectMake(frame.size.width/2-[text sizeWithFont:font].width/2, frame.size.height - 16, [text sizeWithFont:font].width, 15)]; |
28 |
[txt
setFont:[UIFont systemFontOfSize:12]]; |
29 |
[txt
setBackgroundColor:[UIColor clearColor]]; |
30 |
[txt
setTextColor:[UIColor whiteColor]]; |
32 |
[self
addSubview:txt]; |
34 |
button
= [UIButton buttonWithType:UIButtonTypeCustom]; |
35 |
button.frame
= CGRectMake(0, 0, frame.size.width, frame.size.height); |
36 |
[button
setBackgroundColor:[UIColor clearColor]]; |
37 |
button.showsTouchWhenHighlighted
= YES; |
38 |
[button
addTarget:delegate action:@selector(didSelectItem:) forControlEvents:UIControlEventTouchUpInside]; |
39 |
[self
addSubview:button]; |
基本组件代码就是如上所述的,调用代码如下:
09 |
#import
"ViewController.h" |
10 |
#import
"IndexViewController.h" |
12 |
@interface
ViewController () |
16 |
@implementation
ViewController |
22 |
tabbar
= [[MyTabBarController alloc] init]; |
23 |
[tabbar.view
setFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)]; |
24 |
tabbar.delegate
= self; |
27 |
IndexViewController
*one = [[IndexViewController alloc] init]; |
28 |
[one.view
setBackgroundColor:[UIColor redColor]]; |
30 |
IndexViewController
*two = [[IndexViewController alloc] init]; |
31 |
[two.view
setBackgroundColor:[UIColor blueColor]]; |
33 |
IndexViewController
*three = [[IndexViewController alloc] init]; |
34 |
[three.view
setBackgroundColor:[UIColor yellowColor]]; |
36 |
[tabbar
addViewController:one resource:MyTabBarItemMake([UIImage imageNamed:@ "xianhuo.png" ],
[UIImage imageNamed:@ "xianhuo_click.png" ],
[UIImage imageNamed:@ "xianhuo_click.png" ],
@ "现货" )]; |
37 |
[tabbar
addViewController:two resource:MyTabBarItemMake([UIImage imageNamed:@ "zixun.png" ],
[UIImage imageNamed:@ "zixun_click.png" ],
[UIImage imageNamed:@ "zixun_click.png" ],
@ "资讯" )]; |
38 |
[tabbar
addViewController:three resource:MyTabBarItemMake([UIImage imageNamed:@ "qihuo.png" ],
[UIImage imageNamed:@ "qihuo_click.png" ],
[UIImage imageNamed:@ "qihuo_click.png" ],
@ "期货" )]; |
39 |
[tabbar
addEventTabItem:MyTabBarItemMake([UIImage imageNamed:@ "more.png" ],
[UIImage imageNamed:@ "more_click.png" ],
nil, @ "更多" )]; |
43 |
[self.view
addSubview:tabbar.view]; |
47 |
-
( void )
myTabBarController:(MyTabBarController *)tabBarController didSelectViewController:(id)viewController index:( int )index
{ |
50 |
toolView
= [[UIView alloc] initWithFrame:CGRectMake(0, tabbar.mainView.frame.size.height, tabbar.mainView.frame.size.width, 100)]; |
51 |
[toolView
setBackgroundColor:[UIColor scrollViewTexturedBackgroundColor]]; |
52 |
[tabbar.mainView
addSubview:toolView]; |
53 |
[toolView
setAlpha:0]; |
55 |
[UIView
beginAnimations:nil context:nil]; |
57 |
if (toolView.frame.origin.y
>= tabbar.mainView.frame.size.height) { |
58 |
[toolView
setAlpha:1]; |
59 |
toolView.frame
= CGRectMake(0, tabbar.mainView.frame.size.height - 100, tabbar.mainView.frame.size.width, 100); |
61 |
[toolView
setAlpha:0]; |
62 |
toolView.frame
= CGRectMake(0, tabbar.mainView.frame.size.height, tabbar.mainView.frame.size.width, 100); |
64 |
[UIView
commitAnimations]; |
68 |
-
( void )didReceiveMemoryWarning |
70 |
[super
didReceiveMemoryWarning]; |
给个预览图看看(因为素材不是很高清,所以有点模糊,这个换图片就可以了):
前三项为普通的页面切换,最后一项为自定义功能的选项,主要处理代码写在MyTabBarController的protocol回调方法中。
目前该组件还有些问题,比如:为了调用方便,为了一个个添加UIViewController而不是像系统自带的一次性添加一个数组,最后必须调用addDone方法(这问题可以修改,不过目前懒得动了),另外没经过实际项目测试等等。。。