引言
公司有个需求给Button添加badge,网上翻了些资料,感觉调用起来都比较麻烦,github上找了一个1000+star的,竟然有BUG,当然也可能我调用方式有问题,不过总归是实现起来不爽,于是想着自己写个,权当练练手。
实现方式
1, 本着调用简单的原则,首先想到的是通过category的方式。最初的想法是一行代码实现调用
view.badge = @"100"//包含数字的小红点
[view showBadge];//不包含数字的更小的小红点
2,于是给UIView的 category中添两属性,一个暴露在头文件中
@property (nonatomic, copy) NSString *badge;
另一个,在实现文件中
@property (nonatomic, strong) UILabel *badgeLabel;
这两个属性的意思,看名字估计也一目了然,不再赘述。
3,通过关联对象为两个属性实现getter和setter,不懂关联对象请移步 通过关联对象实现UITextView的Placeholde
-
定义key
const char *kZMBadgeKey = "kZMBadgeKey"; const char *kZMBadgeLabelKey = "kZMBadgeLabelKey";
-
getter && setter
- (void)setBadge:(NSString *)badge{ if (badge) { //关联对象 objc_setAssociatedObject(self, &kZMBadgeKey, badge, OBJC_ASSOCIATION_COPY_NONATOMIC); //根据类型创建小红点label [self showBadgeWithBadgeStyle:ZMBadgeStyleNumber]; } else{ //remove小红点 [self.badgeLabel removeFromSuperview]; } } - (NSString *)badge{ return objc_getAssociatedObject(self, &kZMBadgeKey); } - (void)setBadgeLabel:(UILabel *)badgeLabel{ objc_setAssociatedObject(self, &kZMBadgeLabelKey, badgeLabel, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } - (UILabel *)badgeLabel{ return objc_getAssociatedObject(self, &kZMBadgeLabelKey); }
4, 定义两个枚举,分别表示包含数字的小红点和耿小的小红点
typedef NS_ENUM(NSInteger,ZMBadgeStyle) {
ZMBadgeStyleDot = 0,//很小的小红点
ZMBadgeStyleNumber,//包含数字的小红点
};
5,根据类型创建小红点
/**
根据类型创建小红点
@param badgeStyle 小红点类型
*/
- (void)showBadgeWithBadgeStyle:(ZMBadgeStyle)badgeStyle{
switch (badgeStyle) {
case ZMBadgeStyleDot:{
if (!self.badgeLabel) {
self.badgeLabel = [self creatBadgeLabelWithText:nil];
}
break;
}
case ZMBadgeStyleNumber:{
if (!self.badgeLabel) {
self.badgeLabel = [self creatBadgeLabelWithText:self.badge];
}
break;
}
}
[self addSubview:self.badgeLabel];
}
/**
创建BadgeLabel
@param text BadgeLabel的text
@return 返回BadgeLabel
*/
- (UILabel *)creatBadgeLabelWithText:(NSString *)text{
CGFloat badgeWidth = 8;
CGFloat selfWidth = self.frame.size.width;
CGRect frame = CGRectMake(selfWidth - badgeWidth / 2, -badgeWidth / 2, badgeWidth, badgeWidth);
UILabel *label = [[UILabel alloc] initWithFrame:frame];
label.layer.cornerRadius = badgeWidth / 2;
label.layer.masksToBounds = YES;
label.backgroundColor = [UIColor redColor];
label.textAlignment = NSTextAlignmentCenter;
label.font = [UIFont systemFontOfSize:11];
label.textColor = [UIColor whiteColor];
label.text = text;
if (text.length > 0) {
CGFloat badgeWidth = 15;
CGFloat badgeHeight = 15;//badge的高度,也是badge超出self的长度的2倍
label.layer.cornerRadius = badgeWidth / 2;
[label sizeToFit];
if (label.frame.size.width > badgeWidth) {
badgeWidth = label.frame.size.width + 10;
}
CGRect frame = CGRectMake(selfWidth - (badgeWidth - badgeHeight / 2), - badgeHeight / 2, badgeWidth, badgeHeight);
label.frame = frame;
}
return label;
}
6,实现public方法 showBadge
- (void)showBadge{
[self showBadgeWithBadgeStyle:ZMBadgeStyleDot];
}
使用
-
ZMBadgeStyleDot类型
- (void)viewDidLoad { [super viewDidLoad]; UIView *view = [[UIView alloc]initWithFrame:CGRectMake(100, 100, 100, 100)]; [view showBadge]; view.backgroundColor = [UIColor greenColor]; [self.view addSubview:view]; }
运行截图如下
-
ZMBadgeStyleNumber类型
- (void)viewDidLoad { [super viewDidLoad]; UIView *view = [[UIView alloc]initWithFrame:CGRectMake(100, 100, 100, 100)]; view.badge = @"100"; view.backgroundColor = [UIColor greenColor]; [self.view addSubview:view]; }
结束
- 代码还没有仔细测,可能会有bug,希望发现bug后能及时提出来,谢谢。
- 代码地址:github地址