补充
前两天有个读者告诉我,UIButton进行了圆角切割之后红点和数字无法正常显示:
简单测试了一下,确实有这个问题,因为我本人项目是将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上:
图层如下:
正文
相信很多开发者遇到过按钮或图片右上角需要显示红点/数字的需求。
普通图片/按钮/Label右上角显示红点或数字
前段时间,公司项目加入了新闻资讯功能,要求收到普通新闻在新闻logo右上角显示红点,重磅消息在logo右上角显示收到的重磅消息的数量,效果如下图:
方法有很多,比如:写个Label加入cell中放在图片右上角、切换图片等等,本文使用Category对Class进行扩展的方法实现该需求,适用于各种view。
先上代码。
UIView+redPoint.h文件代码如下,分别给出show方法和hide方法:
//
// 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];
方法将其移除即可。
底部TabbarItem右上角显示红点或数字
实现这个需求的时候,我想到先前做的底部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]; //"我的"移除红点
分享完毕。