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