iOS开发笔记2 - 自定义tabbar

来源:互联网 发布:战舰少女r重炮改数据 编辑:程序博客网 时间:2024/04/26 03:12
在开发过程中,TabBarController是几乎每个APP都需要用到的,其内部默认包含一个UITabBar,但这个TabBar并不是很好用,所以我们需要自定义TabBar及上面的Button,以实现我们自己想要的效果。

接下来我们开始自定义。
首先是TabBar的.h文件:

#import <UIKit/UIKit.h>@class DYHTabbar;@protocol DYHTabbarDelegate<NSObject>@optional-(void)tabBar:(DYHTabbar *)tabBar didSelectButtonFrom:(int)from To:(int)to;@end@interface DYHTabbar : UIView@property (nonatomic,weak) id<DYHTabbarDelegate> delegate;-(void)addButtonWithATabbarItem:(UITabBarItem* )item;@end




分析:
1.自定义的TabBar只需要能够在上面放置按钮即可,故我们继承自UIView即可。
2.自定义的TabBar上面的按钮有几个,内容如何,应该由控制器决定,故我们只需要提供API: addButtonWithATabbarItem
让控制器传递一个系统自带的TabBarItem模型给Tabbar来添加按钮
3.很明显控制器需要监听TabBar上按钮的点击,来切换子控制器,故我们定义一个代理协议,由控制器实现

接下来是TabBar的.m文件

#import "DYHTabbar.h"#import "DYHTabbarButton.h"@interface DYHTabbar()@property (nonatomic,strong) NSMutableArray* buttons;@property (nonatomic,weak) DYHTabbarButton* selectedButton;@end@implementation DYHTabbar-(NSMutableArray *)buttons{    if (_buttons == nil) {        _buttons = [NSMutableArray array];    }    return _buttons;}-(void)addButtonWithATabbarItem:(UITabBarItem *)item{    DYHTabbarButton* button = [[DYHTabbarButton alloc]init];    [self addSubview:button];        button.item = item;        [button addTarget:self action:@selector(buttonClick:)forControlEvents:UIControlEventTouchDown];        [self.buttons addObject:button];        if (self.buttons.count == 1) {        [self buttonClick:button];    }}-(void)buttonClick:(DYHTabbarButton *)button{    NSLog(@"buttonClick:");    if ([self.delegaterespondsToSelector:@selector(tabBar:didSelectButtonFrom:To:)]) {        [self.delegate tabBar:selfdidSelectButtonFrom:self.selectedButton.tag To:button.tag];    }    self.selectedButton.selected = NO;    button.selected = YES;    self.selectedButton = button;}-(void)layoutSubviews{    [super layoutSubviews];    CGFloat tabBarH = self.frame.size.height;    CGFloat tabBarW = self.frame.size.width;            CGFloat buttonW = tabBarW / self.buttons.count;    CGFloat buttonH = tabBarH;    CGFloat buttonY = 0;        for (int i = 0; i<self.buttons.count ; i++) {        //取出按钮        DYHTabbarButton* button = self.buttons[i];        //设置按钮的frame        CGFloat buttonX = i*buttonW;        button.frame = CGRectMake(buttonX, buttonY, buttonW, buttonH);        //绑定TAG        button.tag = i;            }}@end



分析:
1.tabbar需要访问内部的按钮,故有数组buttons
2.tabbar需要知道当前被选中的按钮,故有属性selectedButton
3.buttons是mutableArray,故进行懒加载
4.addbutton,添加按钮,接收UITabBarItem模型以设置按钮属性,默认点击第一个按钮,并且每个按钮被点击通知Tabbar
5.buttonClick:按钮被点击的回调方法,由于Tabbar本身没有改变控制器的能力,故必须通知其控制器,执行代理方法,整个消息路径是 button被点击--(通知)-->Tabbar--(通知)-->控制器->执行切换控制器操作。另外,在这个方法中需要设置按钮的点击状态(样式变化)以及Tabbar的selectedButton
6.layoutSubviews,在TabBar加载时自动调用,算出按钮的frame,很简单的算法,要注意的是这里需要set一下按钮的tag值,用来标记这是第几个按钮。


接下来我们来看看自定义的button,由于我们自定义的整个Tabbar本身是透明的,故实际显示的效果全看我们自定义的Button。

.h文件

#import <UIKit/UIKit.h>@interface DYHTabbarButton : UIButton@property (nonatomic,strong) UITabBarItem* item;@end



分析:
1.没什么好说的,一个模型属性来接收模型

.m文件

#import "DYHTabbarButton.h"//图标比例#define DYHTabBarButtonImageRatio 0.7//按钮默认文字颜色#define DYHTabBarButtonTitleColor (iOS7 ? [UIColor blackColor] : [UIColor whiteColor])//选中文字颜色#define DYHTabBarButtonTitleSlectedColor (iOS7 ? DYHColor(234,103,0) : DYHColor(248,139,0))@implementation DYHTabbarButton- (id)initWithFrame:(CGRect)frame{    self = [super initWithFrame:frame];    if (self) {        self.imageView.contentMode =UIViewContentModeCenter;        self.titleLabel.textAlignment = NSTextAlignmentCenter;        self.titleLabel.font = [UIFont systemFontOfSize:10];        [self setTitleColor:DYHTabBarButtonTitleColorforState:UIControlStateNormal];        [self setTitleColor:DYHTabBarButtonTitleSlectedColorforState:UIControlStateSelected];            }    return self;}-(void)setItem:(UITabBarItem *)item{    _item = item;    //KVO 监听属性    [item addObserver:self forKeyPath:@"badgeValue"options:0 context:nil];    [item addObserver:self forKeyPath:@"title" options:0context:nil];    [item addObserver:self forKeyPath:@"image" options:0context:nil];    [item addObserver:self forKeyPath:@"selectedImage"options:0 context:nil];            [self observeValueForKeyPath:nil ofObject:nil change:nilcontext:nil];}//监听到某个对象的属性改变了就会调用-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{        //设置文字和图片    [self setTitle:self.item.title forState:UIControlStateNormal];    [self setImage:self.item.imageforState:UIControlStateNormal];    [self setImage:self.item.selectedImageforState:UIControlStateSelected];    }-(void)dealloc{    [self removeObserver:self forKeyPath:@"badgeValue"];    [self removeObserver:self forKeyPath:@"title"];    [self removeObserver:self forKeyPath:@"image"];    [self removeObserver:self forKeyPath:@"selectedImage"];}-(CGRect)titleRectForContentRect:(CGRect)contentRect{    CGFloat titleY =contentRect.size.height*DYHTabBarButtonImageRatio;    CGFloat titleW =contentRect.size.width;    return CGRectMake(0, titleY, titleW , contentRect.size.height - titleY);    }-(CGRect)imageRectForContentRect:(CGRect)contentRect{    CGFloat imageW = contentRect.size.width;    CGFloat imageH = contentRect.size.height*DYHTabBarButtonImageRatio;    return CGRectMake(0, 0, imageW, imageH);}@end


分析: 1.init没什么好说的,设置一些颜色字体,根据需求来
2.setItem,读取模型数据的方法,需要注意的是这里我们使Item监听自己的值改变,为的是完善逻辑,使用button.item.属性同样也能更改button的样式;另外我们默认调用一次值改变回调方法,初始化。
3.值改变回调方法,没什么好说的,根据值改变设置按钮属性
4.dealloc方法,在这个对象被销毁时停止监听
        5,6用来设置按钮上的文字和图片的显示样式


至此我们的自定义Tabbar完成了,不过controller在使用的时候还有一些要注意的(我们默认使用UITabBarController及其子类):
1.需要写如下代码
-(void)viewWillAppear:(BOOL)animated{        [super viewWillAppear:animated];        for (UIView *child in self.tabBar.subviews) {        if ([child isKindOfClass:[UIControl class]]) {            [child removeFro}mSuperview];        }    }

因为tabBarController内部本身有一个TabBar,执行addChildController操作后默认tabbar也会加上按钮,需要移除这些按钮,否则会造成显示错误。

2.实现代理方法:

-(void)tabBar:(DYHTabbar *)tabBar didSelectButtonFrom:(int)from To:(int)to{    self.selectedIndex = to;}


由于tabBarController本身重写了selectedIndex的set方法,并且我们传的值恰好与子控制器顺序相对应,故只需要这一句代码即可完成切换


0 0
原创粉丝点击