为你的TabBar添加Badge-感谢分享
实现过程
首先定义了三种Badge类型
typedef NS_ENUM(NSUInteger, CustomBadgeType){
kCustomBadgeStyleRedDot, //显示普通红点类型
kCustomBadgeStyleNumber, //显示数字类型
kCustomBadgeStyleNone //不显示
};
然后提供了一个最主要的api, 设置badge
- (void)setBadgeStyle:(CustomBadgeType)type value:(NSInteger)badgeValue atIndex:(NSInteger)index;
下边是设置badge的实现, 主要思路是首先初始化所有的badgeView,比如tabbar items的数量为3,则初始化3个红点badge和数字badge,并把它们都隐藏。然后根据badge的style ,value,index设置显示哪一个红点以及显示什么样式。
-(void)setBadgeStyle:(CustomBadgeType)type value:(NSInteger)badgeValue atIndex:(NSInteger)index{
//判断是否已经初始化过badge,没有的话则计算并添加badge
if( ![[self valueForKey:kBadgeViewInitedKey] boolValue] ){
[self setValue:@(YES) forKey:kBadgeViewInitedKey];
[self addBadgeViews];
}
//获取badge dotViews数组 和 numberViews数组, 分别代表红点badge和数字badge
NSMutableArray *badgeDotViews = [self valueForKey:kBadgeDotViewsKey];
NSMutableArray *badgeNumberViews = [self valueForKey:kBadgeNumberViewsKey];
//设置隐藏badge
[badgeDotViews[index] setHidden:YES];
[badgeNumberViews[index] setHidden:YES];
//根据类型决定显示哪一种badge
if(type == kCustomBadgeStyleRedDot){
[badgeDotViews[index] setHidden:NO];
}else if(type == kCustomBadgeStyleNumber){
[badgeNumberViews[index] setHidden:NO];
UILabel *label = badgeNumberViews[index];
//根据数字来动态更新badge
[self adjustBadgeNumberViewWithLabel:label number:badgeValue];
}else if(type == kCustomBadgeStyleNone){
//empty
}
}
这里初始化badgeViews的思路是使用tabbar的宽度计算出每一个badge的位置,然后添加UIView 和UILabel到tabbar中,并设置一些属性:
-(void)addBadgeViews{
//获取badgeview的横向偏移量和top值
id idIconWith = [self valueForKey:kTabIconWidth];
CGFloat tabIconWidth = idIconWith ? [idIconWith floatValue] : 32;
id idBadgeTop = [self valueForKey:kBadgeTop];
CGFloat badgeTop = idBadgeTop ? [idBadgeTop floatValue] : 11;
NSInteger itemsCount = self.items.count;
CGFloat itemWidth = self.bounds.size.width / itemsCount;
//dotBadge views
NSMutableArray *badgeDotViews = [NSMutableArray new];
for(int i = 0;i < itemsCount;i ++){
UIView *redDot = [UIView new];
redDot.bounds = CGRectMake(0, 0, 10, 10);
redDot.center = CGPointMake(itemWidth*(i+0.5)+tabIconWidth/2, badgeTop);
redDot.layer.cornerRadius = redDot.bounds.size.width/2;
redDot.clipsToBounds = YES;
redDot.backgroundColor = [UIColor redColor];
redDot.hidden = YES;
[self addSubview:redDot];
[badgeDotViews addObject:redDot];
}
//设置属性来记录有哪些dotViews,方便更新dotViews的属性时使用
[self setValue:badgeDotViews forKey:kBadgeDotViewsKey];
//numberBadge views
NSMutableArray *badgeNumberViews = [NSMutableArray new];
for(int i = 0;i < itemsCount;i ++){
UILabel *redNum = [UILabel new];
redNum.layer.anchorPoint = CGPointMake(0, 0.5);
redNum.bounds = CGRectMake(0, 0, 20, 14);
redNum.center = CGPointMake(itemWidth*(i+0.5)+tabIconWidth/2-10, badgeTop);
redNum.layer.cornerRadius = redNum.bounds.size.height/2;
redNum.clipsToBounds = YES;
redNum.backgroundColor = [UIColor redColor];
redNum.hidden = YES;
redNum.textAlignment = NSTextAlignmentCenter;
redNum.font = [UIFont systemFontOfSize:12];
redNum.textColor = [UIColor whiteColor];
[self addSubview:redNum];
[badgeNumberViews addObject:redNum];
}
//设置属性来记录有哪些numberViews,方便更新numberViews的属性时使用
[self setValue:badgeNumberViews forKey:kBadgeNumberViewsKey];
}
上边还有一个函数是根据数字更新badge,实现也很简单武断,如下:
-(void)adjustBadgeNumberViewWithLabel:(UILabel *)label number:(NSInteger)number{
[label setText:(number > 99 ? @"..." : @(number).stringValue)];
if(number < 10){
label.bounds = CGRectMake(0, 0, 14, 14);
}else if(number < 99){
label.bounds = CGRectMake(0, 0, 20, 14);
}else{
label.bounds = CGRectMake(0, 0, 20, 14);
}
}
看完上边,其实大概的逻辑流程都讲清楚了。如果你细心的话,会发现[self setValue:badgeNumberViews forKey:kBadgeNumberViewsKey];
这一句调用是有问题的,如果不处理程序会直接崩溃。我本来是想在extension中定义几个的属性,写起来才觉得很麻烦,因此在stackoverflow上稍微看了几个回答,采用了一个简单点的方法: 重写valueForUndefinedKey:
和setValue:forUndefinedKey:
,并利用objc的动态绑定的方式注入属性,这里其实会有一些陷阱,可以参考我最后附的链接进行详细阅读。代码如下:
-(id)valueForUndefinedKey:(NSString *)key{
return objc_getAssociatedObject(self, (__bridge const void *)(key));
}
-(void)setValue:(id)value forUndefinedKey:(NSString *)key{
objc_setAssociatedObject(self, (__bridge const void *)(key), value, OBJC_ASSOCIATION_COPY);
}
如果你知道更好地方法一定要告诉我 :- )
还有其他的一些api实现比较简单就不列出来了。
使用方法
使用方法相当简单,首先将github上的.h和.m文件加入你的工程,接下来只需要两步:
- 在初始化tabbar的时候,设置badgeview的位置
[tabController.tabBar setTabIconWidth:29];//调整x偏移量
[tabController.tabBar setBadgeTop:9];//调整y偏移量
- 设置显示badgeview的样式
[self.tabBarController.tabBar setBadgeStyle:type value:number atIndex:index];
大功告成!
效果
这里附上一个效果
思考
这个实现还有很多满足了我最简单的需求,还有一些问题需要处理:
- 当tabbar更新时,badgeView并没有随着更新,这里需要添加一种自动的机制来更行
- 还有一些其他的定制比如修改badgeView的颜色,修改badgeView的大小以及badgeView显示字符串而不仅仅是数字目前并没有支持 ,可能我比较懒吧,以后慢慢加上 :-)
参考
- 实现tabbar badge的思路
http://stackoverflow.com/questions/13341603/is-it-possible-to-change-uitabbaritem-badge-color - 在extension中添加property
http://inchoo.net/dev-talk/ios-development/how-to-add-a-property-via-class-category/ - 重写
setValueForUndefinedKey
和valueForUndefined
来注入属性
http://www.cnblogs.com/powerauras/p/3323497.html
本文的源代码以及demo都在github上,需要的请戳这里 MRsummer/CustomBadge。欢迎吐槽~
原文链接:http://www.jianshu.com/p/e8398e3231d5
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
为你的TabBar添加Badge-感谢分享的更多相关文章
- Android中通过ActionBar为标题栏添加搜索以及分享视窗
在Android3.0之后,Google对UI导航设计上进行了一系列的改革,其中有一个非常好用的新功能就是引入的ActionBar,他用于取代3.0之前的标题栏,并提供更为丰富的导航效果.Action ...
- Ext TabPanel tabbar添加按钮
tabPanel tabbar添加按钮 this.tabPanel = Ext.create('Ext.tab.Panel', { tabBar:{ items:[{ //组件靠右 xtype: 't ...
- mysql启动关闭的批处理,感觉很好用在其他论坛帖子上找到的,感谢分享
最近用mysql的时间比较多,每次都在计算机管理工具下面去启动,感觉很麻烦,于是搜索了下果然有前辈已经做出了这些东西,今天收藏整理,mysql启动关闭的批处理感觉很好用在其他论坛帖子上找到的,感谢互联 ...
- Cocos2d-x 添加iOS7默认分享/AirDrop
猴子原创,欢迎转载.转载请注明: 转载自Cocos2D开发网–Cocos2Dev.com,谢谢! 原文地址: http://www.cocos2dev.com/?p=530 下午添加分享的时候,看着这 ...
- 应用程序添加角标和tabBar添加角标,以及后台运行时显示
1.设置角标的代码: // 从后台取出来的数据可能是int型的不能直接给badgeValue(string类型的),需要通过description转化 NSString *count = [re ...
- iOS TabBar添加阴影
效果图如下所示: 直接上代码 //移除顶部线条 self.tabBar.backgroundImage = [UIImage new]; self.tabBar.shadowImage = [UIIm ...
- flutter 自定义tabbar 给tabbar添加背景功能
flutter 自带的tabbar BottomNavigationBar有长按水波纹效果,不可以添加背景图片功能,如果有这方面的需求,就需要自定义tabbar了 自定义图片 我们使用BottomAp ...
- iOS 实现脉冲雷达以及动态增减元素 By Swift-感谢分享
Swift经过Xcode6 Beta4一版更新后,基本上已经可以作为生产工具了,虽然有一些地方和ObjC比起来要“落后”一些,但也无伤大雅.这里就用Xcode6 Beta4+iOS SDK 8.0开发 ...
- Swift 标签控制器(tabbar添加提醒和控制器)
// Override point for customization after application launch. //初始化window, 大小为设备物理大小 self.window = U ...
随机推荐
- .NET技术-.NET各大网站-编程技术网址
Source Code: http://www.codeproject.com/ The Code Projecthttp://www.tomore.com/ 中 国盟动力http://www.cod ...
- 【转】Cocos2d-x纹理优化的一些方案——2013-08-26 22
http://wap.oschina.net/question/565065_79814 在目前的移动平台游戏开发过程中,很多朋友会遇到开发出来的DEMO占用内存过大,导致渲染效率低下的问题.究其原因 ...
- BeagleBone Black Linux驱动程序开发入门(1): LED驱动程序
这篇文章展示如何在BBB平台上编写LED驱动程序,本文的程序是根据国嵌S3C2440的LED驱动的例子并结合内核中OMAP系列的gpio操作来改的.本文中的程序包括驱动程序模块和用户空间程序.废话不多 ...
- Android开发之”再按一次退出程序“的实现
现在移动客户端退出程序对话框退出越来越不流行了,都开始使用连续按两次来退出,即著名的“再按一次退出程序”模式.现在就看看怎么实现的吧. @SuppressLint("HandlerLeak& ...
- Android和Java的轻巧Wire协议缓冲器
Wire协议缓冲器 一个人必须有一个代码! -奥马尔小 由于我们的团队和项目增长,数据的种类和数量也随之增加. 成功将您简单的数据模型转换为复杂的! 无论您的应用程序将数据存储到磁盘或网络传送信号,该 ...
- ActiveMQ系列(1) - 使用入门
没网的日子真的不好过啊 1.背景: 对于常见业务中,数据并发是一个很头疼的问题,很多时候,会出现资源共享导致线程阻塞的问题,这时候问题就来了,,,老板也尾随来了,来 ...
- HTML 学习整理
一.名词解释 一. HTML : Hypertext Markup Language 超文本标记语言 二. CSS : Cascading Style Sheet 层叠样式表 三. 浏览器: ...
- poj1308 Is It A Tree?(并查集)详解
poj1308 http://poj.org/problem?id=1308 题目大意:输入若干组测试数据,输入 (-1 -1) 时输入结束.每组测试数据以输入(0 0)为结束标志.然后根据所给的 ...
- java swing窗口放置屏幕中央问题思考
java swing窗口放置屏幕中央问题思考 以前总是尝试各种方法都没有能把组件放到屏幕中央,只能用死办法,设置绝对坐标,但这样就失去了可移植性,而且繁琐.今天仔细思考了一番,终于被我找出问题所在. ...
- ZOJ 1013 Great Equipment(DP)
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=13 题目大意:说的是有三种不同的装备,分别是头盔,盔甲,战靴需要运输, ...