前两天有个读者告诉我,UIButton进行了圆角切割以后红点和数字没法正常显示:ide
简单测试了一下,确实有这个问题,由于我本人项目是将Image绘制成圆形,因此没有发现这个问题,通常不直接对控件进行处理。学习
1.不切割控件,将Image绘制成须要的圆形:测试
//图像圆角切割 - (UIImage *)ymtGetCornerRadius:(CGFloat)cornerRadius { CGFloat scale = [UIScreen mainScreen].scale; UIGraphicsBeginImageContextWithOptions(self.size, NO, scale); CGContextRef c = UIGraphicsGetCurrentContext(); CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height); UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:cornerRadius]; CGContextAddPath(c, path.CGPath); CGContextClip(c); [self drawInRect:rect]; CGContextDrawPath(c, kCGPathFillStroke); UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return image; }
2.在button外面套一个空白的view,红点显示在view上:spa
图层以下:code
相信不少开发者遇到过按钮或图片右上角须要显示红点/数字的需求。orm
前段时间,公司项目加入了新闻资讯功能,要求收到普通新闻在新闻logo右上角显示红点,重磅消息在logo右上角显示收到的重磅消息的数量,效果以下图:继承
方法有不少,好比:写个Label加入cell中放在图片右上角、切换图片等等,本文使用Category对Class进行扩展的方法实现该需求,适用于各类view。图片
先上代码。ip
UIView+redPoint.h文件代码以下,分别给出show方法和hide方法:ci
// // UIView+redPoint.h // Medicine // // Created by zhujiamin on 16/4/16. // Copyright © 2016年 MedEx. All rights reserved. // #import <UIKit/UIKit.h> @interface UIView (redPoint) - (void)showRedAtOffSetX:(float)offsetX AndOffSetY:(float)offsetY OrValue:(NSString *)value; - (void)hideRedPoint; @end
UIView+redPoint.m文件中具体方法实现以下:
#pragma other(redPoint) //添加显示 - (void)showRedAtOffSetX:(float)offsetX AndOffSetY:(float)offsetY OrValue:(NSString *)value{ [self removeRedPoint];//添加以前先移除,避免重复添加 //新建小红点 UIView *badgeView = [[UIView alloc]init]; badgeView.tag = 998; CGFloat viewWidth = 12; if (value) { viewWidth = 18; UILabel *valueLbl = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, viewWidth, viewWidth)]; valueLbl.text = value; valueLbl.font = FONT_12; valueLbl.textColor = [UIColor whiteColor]; valueLbl.textAlignment = NSTextAlignmentCenter; valueLbl.clipsToBounds = YES; [badgeView addSubview:valueLbl]; } badgeView.layer.cornerRadius = viewWidth / 2; badgeView.backgroundColor = [UIColor redColor]; CGRect tabFrame = self.frame; //肯定小红点的位置 if (offsetX == 0) { offsetX = 1; } if (offsetY == 0) { offsetY = 0.05; } CGFloat x = ceilf(tabFrame.size.width + offsetX); CGFloat y = ceilf(offsetY * tabFrame.size.height); badgeView.frame = CGRectMake(x, y, viewWidth, viewWidth); [self addSubview:badgeView]; } //隐藏 - (void)hideRedPoint{ [self removeRedPoint]; } //移除 - (void)removeRedPoint{ //按照tag值进行移除 for (UIView *subView in self.subviews) { if (subView.tag == 998) { [subView removeFromSuperview]; } } }
为了知足不一样位置的显示
- (void)showRedAtOffSetX:(float)offsetX AndOffSetY:(float)offsetY OrValue:(NSString *)value;
此方法接收调用时给入想要显示的红点或者数字相对父view的最大X值的偏移,和高度的倍数;
if (offsetX == 0) { offsetX = 1; } if (offsetY == 0) { offsetY = 0.05; } CGFloat x = ceilf(tabFrame.size.width + offsetX); CGFloat y = ceilf(offsetY * tabFrame.size.height);
默认须要显示在右上角时,offsetX和offsetY能够设置为0,根据具体需求给出不一样的数值便可;
本例须要Button右上角显示红点,须要显示红点时Value值赋为nil,若需显示数字则赋值相应的字符便可,调用方法以下:
[centerBtn showRedAtOffSetX:0 AndOffSetY:0 OrValue:nil]; [centerBtn showRedAtOffSetX:0 AndOffSetY:0 OrValue:@"2"];
须要隐藏红点/数字时只须要调用
[sender hideRedPoint];
方法将其移除便可。
实现这个需求的时候,我想到先前作的底部tabbar下的item显示红点的方法,使用的是粗暴的切换图片方法,实际上UITabbar也继承于UIView,这种思路一样适用,不过tabbar只须要显示和隐藏红点便可,显示数字使用系统的badgeValue赋值便可,效果以下:
因而我在UIView+redPoint.h文件中加入了如下两个方法供UITabbar调用,index参数为要显示红点的item的序号。
//tabbar方法 - (void)showBadgeOnItemIndex:(int)index; //显示小红点 - (void)hideBadgeOnItemIndex:(int)index; //隐藏小红点
具体实现方法和前面讲到的其余控件显示方法相似,只不过要准确计算显示红点的位置,具体实现以下:
#define USERDEF [NSUserDefaults standardUserDefaults] //宏定义NSUserDefaults用来存本地标记
#pragma mark Tabbar(redPoint) //显示小红点 - (void)showBadgeOnItemIndex:(int)index{ NSString *keyStr = [NSString stringWithFormat:@"%d_HADSET",index]; if ([USERDEF objectForKey:keyStr]) { return; } else { [USERDEF setObject:@"HADSET" forKey:keyStr]; } //移除以前可能存在的小红点 [self removeBadgeOnItemIndex:index]; //新建小红点 UIView *badgeView = [[UIView alloc]init]; badgeView.tag = 888 + index; badgeView.layer.cornerRadius = 6; badgeView.backgroundColor = [UIColor redColor]; CGRect tabFrame = self.frame; //肯定小红点的位置 float percentX = (index +0.55) / 5; //5为tabbaritem的总个数 CGFloat x = ceilf(percentX * tabFrame.size.width); CGFloat y = ceilf(0.05 * tabFrame.size.height); badgeView.frame = CGRectMake(x, y, 12, 12); [self addSubview:badgeView]; } //隐藏小红点 - (void)hideBadgeOnItemIndex:(int)index{ NSString *keyStr = [NSString stringWithFormat:@"%d_HADSET",index]; //移除小红点 [self removeBadgeOnItemIndex:index]; if ([USERDEF objectForKey:keyStr]) { [USERDEF removeObjectForKey:keyStr]; } } //移除 - (void)removeBadgeOnItemIndex:(int)index{ //按照tag值进行移除 for (UIView *subView in self.subviews) { if (subView.tag == 888+index) { [subView removeFromSuperview]; } } }
由于tabar红点设置方法调用比较频繁,为了不每次重复移除重设操做,我在红点show成功以后会对当前item进行本地标记,每次调用showBadgeOnItemIndex:方法会先判断当前index是否已经显示红点,已经显示则不在重复设置,调用hideBadgeOnItemIndex:方法时,移除该标记。
NSString *keyStr = [NSString stringWithFormat:@"%d_HADSET",index]; if ([USERDEF objectForKey:keyStr]) { return; } else { [USERDEF setObject:@"HADSET" forKey:keyStr]; }
NSString *keyStr = [NSString stringWithFormat:@"%d_HADSET",index]; if ([USERDEF objectForKey:keyStr]) { [USERDEF removeObjectForKey:keyStr]; }
显示/隐藏调用方法以下:
[self.tabBarController.tabBar showBadgeOnItemIndex:4]; //"个人"显示红点 [self.tabBarController.tabBar hideBadgeOnItemIndex:4]; //"个人"移除红点
分享完毕。
本人坐标杭州,后续我会陆续把工做中遇到的问题及解决方案分享出来,互相交流学习,本人QQ:815187811,欢迎结交[笑脸].