自定义TabBar

先自定义一个UITabBarController,为了方便跳转与设定属性,借助系统的TabBarController的功能,但是要移除内部的控件然后自己添加一个View和多个按钮。

首先要移除已有的TabBarItem,通过判断是否是TabBarItem,但是TabBarItem是私有类,不让直接判断。

因此通过判断父类类型来检查。

要得到这些控件,需要在viewWillAppear方法中:

- (void)viewWillAppear:(BOOL)animated{

    [super viewWillAppear:animated];
NSLog(@"%d",self.tabBar.subviews.count); for (UIView *chind in self.tabBar.subviews) { NSLog(@"%@",chind.superclass); } }

查看打印可以发现,TabBarButtonItem的父类是UIControl,而UITabBar的父类是UIView。

2015-03-08 16:36:41.244 myWeibo[4832:140039] 5

2015-03-08 16:36:41.245 myWeibo[4832:140039] UIView

2015-03-08 16:36:41.245 myWeibo[4832:140039] UIControl

2015-03-08 16:36:41.245 myWeibo[4832:140039] UIControl

2015-03-08 16:36:41.245 myWeibo[4832:140039] UIControl

2015-03-08 16:36:41.245 myWeibo[4832:140039] UIControl

注意,通过isKindOfClass方法,可以判断多态性,例如TabBarButtonItem继承自UIControl,那么使用这个方法判断是否是UIControl,会返回真。

- (void)viewWillAppear:(BOOL)animated{

    [super viewWillAppear:animated];

    for (UIView *chind in self.tabBar.subviews) {

        if ([chind isKindOfClass:[UIControl class]]) {
[chind removeFromSuperview];
} } }

虽然是自定义TabBar,但是为了方便设置各个部分的属性,还是先设置tabBarItem的属性,然后把tabBarItem作为一个模型使用,传给自定义的TabBar来设置,不要忘了用上面的办法把系统自带的barButton给移除。

要自定义TabBar,首先自定义UIView用于绘制:

定义一个方法,传入tabBarItem,在tabBar上新建一个按钮,注意在这个方法中不能设置尺寸等属性。

- (void)addTabBarButtonWithItem:(UITabBarItem *)item{

    UIButton *button = [[UIButton alloc] init];
[self addSubview:button]; [button setTitle:item.title forState:UIControlStateNormal];
[button setImage:item.image forState:UIControlStateNormal];
[button setImage:item.selectedImage forState:UIControlStateSelected]; }

通过layoutSubviews方法设定子控件尺寸

- (void)layoutSubviews{

    [super layoutSubviews];

    CGFloat buttonW = self.frame.size.width / self.subviews.count;
CGFloat buttonH = self.frame.size.height; for (int index = 0; index < self.subviews.count; index ++) { UIButton *btn = self.subviews[index];
CGFloat buttonX = buttonW * index;
CGFloat buttonY = 0;
btn.frame = CGRectMake(buttonX, buttonY, buttonW, buttonH); } }

在控制器中,新建一个上面的View的成员变量,注意View使用weak即可:

@property (nonatomic, weak) myTabBar *customTabBar;

注意首先创建自定义tabBar,然后再进行后续的设置:

利用原来的TabBar尺寸可以快速设定自定义TabBar尺寸,注意使用bounds(以自己为参考,x=y=0).

- (void)setupTabBar{
myTabBar *customTabBar = [[myTabBar alloc] init];
customTabBar.backgroundColor = [UIColor grayColor];
customTabBar.frame = self.tabBar.bounds;
[self.tabBar addSubview:customTabBar];
self.customTabBar = customTabBar;
}

注意先用强指针创建再指过去,否则会被释放。

然后定义一个方法用于将一个子控制器的根控制器设为TabBar控制器,然后设置barItem:

注意最后调用自定义View的方法向自定义TabBar上添加控件。

- (void)setupChindViewController:(UIViewController *)chindVc title:(NSString *)title imageName:(NSString *)imageName selectedImageName:(NSString *)selectedImageName{

    chindVc.title = title;
chindVc.tabBarItem.image = [UIImage imageWithName:imageName];
if (iOS7) {
chindVc.tabBarItem.selectedImage = [[UIImage imageWithName:selectedImageName] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
}else{
chindVc.tabBarItem.selectedImage = [UIImage imageWithName:selectedImageName];
} UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:chindVc];
[self addChildViewController:nav]; [self.customTabBar addTabBarButtonWithItem:chindVc.tabBarItem]; }

多次调用完成每个视图的添加:

- (void)setupAllChindViewControllers{
// 首页
HomeViewController *home = [[HomeViewController alloc] init];
[self setupChindViewController:home title:@"首页" imageName:@"tabbar_home" selectedImageName:@"tabbar_home_selected"]; // 消息
MessageViewController *message = [[MessageViewController alloc] init];
[self setupChindViewController:message title:@"消息" imageName:@"tabbar_message_center" selectedImageName:@"tabbar_message_center_selected"]; // 广场
DiscoverViewController *ground = [[DiscoverViewController alloc] init];
[self setupChindViewController:ground title:@"广场" imageName:@"tabbar_discover" selectedImageName:@"tabbar_discover_selected"]; // 我
MyViewController *me = [[MyViewController alloc] init];
[self setupChindViewController:me title:@"我" imageName:@"tabbar_profile" selectedImageName:@"tabbar_profile_selected”]; }

因此只需要先调用方法初始化tabBar,再调用上面的方法即可创建完毕,不要忘记viewWillAppear方法中移除原来的按钮。

- (void)viewDidLoad {

    [super viewDidLoad];
[self setupTabBar];
[self setupAllChindViewControllers]; }

注意,因为先添加的自定义View又添加的barItem,因此自定义View在底层,因此如果不移除系统自带的barItem,会盖在上面。

注意这样做完以后,按钮是左右结构,不符合barItem的上下结构,因此要自定义按钮,重写返回rect的方法来设定图片和标题位置。

为了让二者居中,让按钮的图片水平铺满、竖直占据60%,标题也水平铺满,竖直占据40%,接着让内容居中即可。

#define myTabBarButtonImageRatio 0.6
- (CGRect)imageRectForContentRect:(CGRect)contentRect{
return CGRectMake(0, 0, contentRect.size.width, contentRect.size.height * myTabBarButtonImageRatio);
}
- (CGRect)titleRectForContentRect:(CGRect)contentRect{
CGFloat titleY = contentRect.size.height * myTabBarButtonImageRatio;
return CGRectMake(0, titleY, contentRect.size.width, contentRect.size.height - titleY);
}

因为是自定义的按钮,因此可以将按钮的状态设置封装在内部,可以借鉴前面,传入item模型即可,给按钮类增加item成员变量,重写set方法:

- (void)setItem:(UITabBarItem *)item{
[self setTitle:item.title forState:UIControlStateNormal];
[self setImage:item.image forState:UIControlStateNormal];
[self setImage:item.selectedImage forState:UIControlStateSelected];
}

因为按钮只有选中和普通两种状态,因此取消高亮功能,重写高亮方法,什么也不做:

- (void)setHighlighted:(BOOL)highlighted{};

对于一次性设置的属性,例如按钮的颜色等,放入initWithFrame方法:设置颜色如果使用rgb不要忘了/255.0

- (id)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if (self) {
self.imageView.contentMode = UIViewContentModeCenter;
self.titleLabel.textAlignment = NSTextAlignmentCenter;
self.titleLabel.font = [UIFont systemFontOfSize:12];
[self setTitleColor:myTabBarButtonColor forState:UIControlStateNormal];
[self setTitleColor:myTabBarButtonSelectedColor forState:UIControlStateSelected];
if (!iOS7) {
[self setBackgroundImage:[UIImage imageNamed:@"tabbar_slider"] forState:UIControlStateSelected];
}
}
return self;
}

这样设置完了以后,就完成了和系统一样的TabBar的样式,并且具有极高的自由度。

但是还不能切换控制器,可以在添加按钮时将index绑定到tag,通过代理传递给TabBar控制器。

给每个按钮绑定点击方法,设定选中:

注意提前给TabBar控制器一个selectedBtn属性,来保存之前选中的按钮。

- (void)buttonClick:(myTabBarButton *)btn{

    if ([self.delegate respondsToSelector:@selector(tabBar:didSelectButtonFrom:to:)]) {
[self.delegate tabBar:self didSelectButtonFrom:self.selectedBtn.tag to:btn.tag];
} self.selectedBtn.selected = NO;
btn.selected = YES;
self.selectedBtn = btn;
}

TabBarController通过selectedIndex可以切换内部绑定的控制器。

注意from to是从原来选中的哪个跳到现在选中的这个。

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

(六十三)自定义TabBar和TabBarButtonItem的更多相关文章

  1. 孤荷凌寒自学python第六十三天学习mongoDB的基本操作并进行简单封装2

    孤荷凌寒自学python第六十三天学习mongoDB的基本操作并进行简单封装2 (完整学习过程屏幕记录视频地址在文末) 今天是学习mongoDB数据库的第九天. 今天继续学习mongoDB的简单操作, ...

  2. 自定义tabBar

    ★★★★自定义tabBar★★★★★★★ Demo下载地址:https://github.com/marlonxlj/tabBarCustom.git 前言: 有的时候需求要对tabBar进行自定义的 ...

  3. IOS第二天-新浪微博 - 添加搜索框,弹出下拉菜单 ,代理的使用 ,HWTabBar.h(自定义TabBar)

    ********HWDiscoverViewController.m(发现) - (void)viewDidLoad { [super viewDidLoad]; // 创建搜索框对象 HWSearc ...

  4. iOS 隐藏自定义tabbar

    iOS  隐藏自定义tabbar -(void)viewWillAppear:(BOOL)animated { NSArray *array=self.tabBarController.view.su ...

  5. iOS开发之功能模块--关于自定义TabBar条

    只上项目中用到的代码: 1.实现重写TabBar的TabBarItem,然后在中间额外加一个按钮. #import <UIKit/UIKit.h> @interface BikeTabBa ...

  6. iOS开发项目之四 [ 调整自定义tabbar的位置与加号按钮的位置]

    自定义tabbar与按钮的添加 01 - 把系统的tabbar用我们自己的覆盖 LHQTabBar *lhqTabBar = [[LHQTabBar alloc]init]; [self setVal ...

  7. 关于自定义tabBar时修改系统自带tabBarItem属性造成的按钮顺序错乱的问题相关探究

      关于自定义tabBar时修改系统自带tabBarItem属性造成的按钮顺序错乱的问题相关探究 测试代码:http://git.oschina.net/Xiyue/TabBarItem_TEST 简 ...

  8. 第二篇、Swift_自定义 tabbar 的 badgeValue显示样式

    在实际的开发中,我们常常需要根据实际的需求,去改变bageValue的显示样式,默认是红色的背景,白色的字体颜色 使用方式: class BKTabBarController: UITabBarCon ...

  9. [iOS微博项目 - 1.6] - 自定义TabBar

    A.自定义TabBar 1.需求 控制TabBar内的item的文本颜色(普通状态.被选中状态要和图标一致).背景(普通状态.被选中状态均为透明) 重新设置TabBar内的item位置,为下一步在Ta ...

随机推荐

  1. Oracle监听启动时报TNS-00507问题

    Linux系统中,启动oracle监听的时候报如下错误: [oracle@centos ~]$ lsnrctl start LSNRCTL :: Copyright (c) , , Oracle. A ...

  2. java里String类为何被设计为final

    前些天面试遇到一个非常难的关于String的问题,"String为何被设计为不可变的"?类似的问题也有"String为何被设计为final?"个人认为还是前面一 ...

  3. ACM Bone Collector

      Many years ago , in Teddy's hometown there was a man who was called "Bone Collector". Th ...

  4. PHP – AJAX 与 PHP

    AJAX 被用于创建交互性更强的应用程序. AJAX PHP 实例 下面的实例将演示当用户在输入框中键入字符时,网页如何与 Web 服务器进行通信: 实例 尝试在输入框中输入一个名字,如:Anna: ...

  5. 异步请求引发的Chrome死锁

    浏览器支持的并发异步请求数目是有限的,当需要的资源过多时候(远远大于并发数目),就需要自己管理XHR请求. 在实现自己的XHR的Manger时候,当请求数目达到2000多的时候,经常会遇到chrome ...

  6. 《Non-Negative Matrix Factorization for Polyphonic Music Transcription》译文

    NMF(非负矩阵分解),由于其分解出的矩阵是非负的,在一些实际问题中具有非常好的解释,因此用途很广.在此,我给大家介绍一下NMF在多声部音乐中的应用.要翻译的论文是利用NMF转录多声部音乐的开山之作, ...

  7. 手把手教你做一个Shell命令窗口

    这是一个类似于win下面的cmd打开后的窗口,可以跨平台使用,可以在win和linux下面同时使用,主要功能如下: 首先我们需要把这些功能的目录写出来,通过写一个死循环,让其每次回车之后都可以保持同样 ...

  8. Android的AIDL机制

    Android 接口定义语言 (AIDL) AIDL(Android 接口定义语言)与您可能使用过的其他 IDL 类似. 您可以利用它定义客户端与服务使用进程间通信 (IPC) 进行相互通信时都认可的 ...

  9. Java基础之枚举妙用

    对于枚举,初学Java的时候可能我们就已经接触过了,但是在毕业前,其实一直都不知道真正工作里面枚举是怎么用的,枚举有什么用?接下来,博主就介绍枚举在实际工作中的一种使用场景,本文只适合初级的小菜鸟看哈 ...

  10. Unity UGUI图文混排(五) -- 一张图集对应多个Text

    继上一篇说的更新了一张图集对应多个Text的功能,为了节省资源嘛 这里,但是也没有舍弃之前的一个Text一个图集,因为我感觉应该两个都有用,于是我重新写了一个脚本 1.其实大体跟前面的都没变,解析标签 ...