1、内部实现细节分析
我们尝试去打印tabBar,看看一个没有进行操作的UITarBarController是怎么样的:
- UITabBarController *tabBarController = [[UITabBarController alloc]init];
- NSLog(@"%@",tabBarController.tabBar.subviews);
结果发现打印出来是这样的:
(>_<) 是空的,不过没关系,我们可以通过写一个继承于UITabBarController的类,来查看内部细节
新建一个继承于UITabBarController类的类NTTabBarController,然后在viewDidLoad中为self添加4个子控制器接着
在viewDidAppear中打印这样一句代码(在viewDidLoad中打印是没有结果的)
- - (void)viewDidAppear:(BOOL)animated
- {
- NTLog(@"%@",self.tabBar.subviews);
- }
打印出来的结果是这样:
- (
- "<_UITabBarBackgroundView: 0x7fcd927a1b40; frame = (0 0; 320 49); autoresize = W; userInteractionEnabled = NO; layer = <CALayer: 0x7fcd927070c0>>",
- "<UITabBarButton: 0x7fcd92453690; frame = (2 1; 76 48); opaque = NO; layer = <CALayer: 0x7fcd92454640>>",
- "<UITabBarButton: 0x7fcd9279d810; frame = (82 1; 76 48); opaque = NO; layer = <CALayer: 0x7fcd92426010>>",
- "<UITabBarButton: 0x7fcd92458a80; frame = (162 1; 76 48); opaque = NO; layer = <CALayer: 0x7fcd92459450>>",
- "<UITabBarButton: 0x7fcd9245c4b0; frame = (242 1; 76 48); opaque = NO; layer = <CALayer: 0x7fcd92426570>>",
- "<UIImageView: 0x7fcd9245db40; frame = (0 -0.5; 320 0.5); autoresize = W; userInteractionEnabled = NO; layer = <CALayer: 0x7fcd92426de0>>"
- )
在分析之前,需要明确几个参数值,导航栏的高度是49,iphone5之前屏幕宽度都是320,iphone6的屏幕宽度是375,iphone6 plus的屏幕宽度是414。
(1)第一个是UITabBarBackgroundView类,我们好像从来都没有使用过这个类,接着去试着敲出这个类,发现没有提示,那么就说明这个类是私有的,苹果不希望外部去访问和操作它。不过通过这个类的命名以及frame来看,这个类是tarBar中于背景相关的。
(2)最后一个是UIImageView类,这个对于大家当然是很熟悉的,通过看它的frame,它的宽度是320,然后高度仅仅为0.5,那么我们联想到的是tabBar中的最上面的分割线。
(3)中间有4个UITabBarButton类的对象,这个类也是私有的,通过查看frame,可以知道苹果所设计的tabBar中都是宽76,高48这样的尺寸的。
了解完了内部结构之后,进一步深入到tarBar中去讨论:新建一个继承于UITabBar的类NTTabBar,同时在以上所使用的NTTabBarController中去使用NTTabBar而不是系统所给的UITabBar,导入NTTabBar类,我们尝试去赋值self.tarBar:
- self.tabBar = [[NTTabBar alloc]init];
但是xcode报错,错误为:
Assignment to readonly property --->试图修改只读属性,按住command然后点击tarBar,在文章中发现:
- @property(nonatomic,readonly) UITabBar *tabBar
那么这时候我们可以使用KVC进行修改,无论属性是通过什么来修饰的,都是可以使用KVC进行赋值修改的:
- [self setValue:[[NTTabBar alloc]init] forKeyPath:@"tabBar"];
这时候就可以在我们自定义的NTTabBar类中进行详细操作:
我们知道对于一个控件中子控件的排布,都是写在了layoutSubViews里面。我们在自定义的NTTabBar中去重写layoutSubViews方法:
- - (void)layoutSubviews
- {
- NSLog(@"%@",self.subviews);
- }
这样打印的结果为:
- (
- "<UITabBarButton: 0x7fe5b9c3ed00; frame = (2 1; 76 48); opaque = NO; layer = <CALayer: 0x7fe5b9c3fcb0>>",
- "<UITabBarButton: 0x7fe5b9f9eaa0; frame = (82 1; 76 48); opaque = NO; layer = <CALayer: 0x7fe5b9f9afc0>>",
- "<UITabBarButton: 0x7fe5b9fa92a0; frame = (162 1; 76 48); opaque = NO; layer = <CALayer: 0x7fe5b9f9e710>>",
- "<UITabBarButton: 0x7fe5b9e6dbf0; frame = (242 1; 76 48); opaque = NO; layer = <CALayer: 0x7fe5b9e6e0a0>>"
- )
可以发现,这里只有我们添加到4个子控制器对应的UITabBarButton,而没有那个作为背景的UITabBarBackgroundView,和作为分隔线的UIImageView。
我们又尝试修改:
- - (void)layoutSubviews
- {
- [super layoutSubviews];
- NSLog(@"%@",self.subviews);
- }
这样打印出来的结果为:
- (
- "<_UITabBarBackgroundView: 0x7fa952c17ab0; frame = (0 0; 320 49); autoresize = W; userInteractionEnabled = NO; layer = <CALayer: 0x7fa952c7f430>>",
- "<UITabBarButton: 0x7fa952d52d30; frame = (2 1; 76 48); opaque = NO; layer = <CALayer: 0x7fa952d53d20>>",
- "<UITabBarButton: 0x7fa952ccd770; frame = (82 1; 76 48); opaque = NO; layer = <CALayer: 0x7fa952ccd5d0>>",
- "<UITabBarButton: 0x7fa952e3ea80; frame = (162 1; 76 48); opaque = NO; layer = <CALayer: 0x7fa952e3f370>>",
- "<UITabBarButton: 0x7fa952e42370; frame = (242 1; 76 48); opaque = NO; layer = <CALayer: 0x7fa952e3e970>>",
- "<UIImageView: 0x7fa952e4af60; frame = (0 -0.5; 320 0.5); autoresize = W; userInteractionEnabled = NO; layer = <CALayer: 0x7fa952e36650>>"
- )
这时候那两个控件就出来了,这是因为调用了super的方法。
2、重写构造tarBar内部结构
首先需要明确的是,对于UIView类或者是UIView类的子类,我们都需要在layoutSubViews里面去控制,所以我们在layoutSubViews里面进行重新布局(本例是模仿新浪微博的tarBar):
- #import "NTTabBar.h"
-
- @interface NTTabBar()
- @property (nonatomic , strong) UIButton *middleButton;
- @end
-
- @implementation NTTabBar
-
-
- - (UIButton *)middleButton
- {
- if (_middleButton == nil) {
- _middleButton = [UIButton buttonWithType:UIButtonTypeCustom];
- [_middleButton setBackgroundImage:[UIImage imageNamed:@"tabbar_compose_button"] forState:UIControlStateNormal];
- [_middleButton setBackgroundImage:[UIImage imageNamed:@"tabbar_compose_button_highlighted"] forState:UIControlStateHighlighted];
- [_middleButton setImage:[UIImage imageNamed:@"tabbar_compose_icon_add" ] forState:UIControlStateNormal];
- [_middleButton setImage:[UIImage imageNamed:@"tabbar_compose_icon_add_highlighted"] forState:UIControlStateHighlighted];
- }
- return _middleButton;
- }
-
- - (void)layoutSubviews
- {
-
- [super layoutSubviews];
-
- int index = 0;
- for (UIView *view in self.subviews) {
-
- if ([view isKindOfClass:NSClassFromString(@"UITabBarButton")]) {
-
- view.width = 320 / 5;
-
- view.x = index * 320/5;
-
- if(index == 1){
- index++;
-
- self.middleButton.height = 48;
- self.middleButton.width = 320/5;
- self.middleButton.x = index * 320/5;
- self.middleButton.y = 2;
- [self addSubview:self.middleButton];
- }
- index++;
- }
- }
- }
- @end
通过在layoutSubViews方法中对进行操作,使得tarBar就变为了我们希望看到的效果: