123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407 |
- //
- // UIView+WZLBadge.m
- // WZLBadgeDemo
- //
- // Created by zilin_weng on 15/6/24.
- // Copyright (c) 2015年 Weng-Zilin. All rights reserved.
- //
- #import "UIView+WZLBadge.h"
- #import <objc/runtime.h>
- #import "CAAnimation+WAnimation.h"
- #define kWZLBadgeDefaultFont ([UIFont boldSystemFontOfSize:9])
- #define kWZLBadgeDefaultMaximumBadgeNumber 99
- static const CGFloat kWZLBadgeDefaultRedDotRadius = 4.f;
- @implementation UIView (WZLBadge)
- #pragma mark -- public methods
- /**
- * show badge with red dot style and WBadgeAnimTypeNone by default.
- */
- - (void)showBadge
- {
- [self showBadgeWithStyle:WBadgeStyleRedDot value:0 animationType:WBadgeAnimTypeNone];
- }
- /**
- * showBadge
- *
- * @param style WBadgeStyle type
- * @param value (if 'style' is WBadgeStyleRedDot or WBadgeStyleNew,
- * this value will be ignored. In this case, any value will be ok.)
- */
- - (void)showBadgeWithStyle:(WBadgeStyle)style value:(NSInteger)value animationType:(WBadgeAnimType)aniType
- {
- self.aniType = aniType;
- switch (style) {
- case WBadgeStyleRedDot:
- [self showRedDotBadge];
- break;
- case WBadgeStyleNumber:
- [self showNumberBadgeWithValue:value];
- break;
- case WBadgeStyleNew:
- [self showNewBadge];
- break;
- default:
- break;
- }
- if (aniType != WBadgeAnimTypeNone) {
- [self beginAnimation];
- }
- }
- - (void)showNumberBadgeWithValue:(NSInteger)value animationType:(WBadgeAnimType)aniType {
- self.aniType = aniType;
- [self showNumberBadgeWithValue:value];
-
- if (aniType != WBadgeAnimTypeNone) {
- [self beginAnimation];
- }
- }
- /**
- * clear badge
- */
- - (void)clearBadge
- {
- self.badge.hidden = YES;
- }
- /**
- * make bage(if existing) not hiden
- */
- - (void)resumeBadge
- {
- if (self.badge && self.badge.hidden == YES) {
- self.badge.hidden = NO;
- }
- }
- #pragma mark -- private methods
- - (void)showRedDotBadge
- {
- [self badgeInit];
- //if badge has been displayed and, in addition, is was not red dot style, we must update UI.
- if (self.badge.tag != WBadgeStyleRedDot) {
- self.badge.text = @"";
- self.badge.tag = WBadgeStyleRedDot;
- [self resetBadgeForRedDot];
- self.badge.layer.cornerRadius = CGRectGetWidth(self.badge.frame) / 2;
- }
- self.badge.hidden = NO;
- }
- - (void)resetBadgeForRedDot {
- if (self.badgeRadius > 0) {
- self.badge.frame = CGRectMake(self.badge.center.x - self.badgeRadius, self.badge.center.y + self.badgeRadius , self.badgeRadius * 2, self.badgeRadius *2);
- }
- }
- - (void)showNewBadge
- {
- [self badgeInit];
- //if badge has been displayed and, in addition, is not red dot style, we must update UI.
- if (self.badge.tag != WBadgeStyleNew) {
- self.badge.text = @"new";
- self.badge.tag = WBadgeStyleNew;
-
- CGRect frame = self.badge.frame;
- frame.size.width = 22;
- frame.size.height = 13;
- self.badge.frame = frame;
-
- self.badge.center = CGPointMake(CGRectGetWidth(self.frame) + 2 + self.badgeCenterOffset.x, self.badgeCenterOffset.y);
- self.badge.font = kWZLBadgeDefaultFont;
- self.badge.layer.cornerRadius = CGRectGetHeight(self.badge.frame) / 3;
- }
- self.badge.hidden = NO;
- }
- - (void)showNumberBadgeWithValue:(NSInteger)value
- {
- if (value < 0) {
- return;
- }
- [self badgeInit];
- self.badge.hidden = (value == 0);
- self.badge.tag = WBadgeStyleNumber;
- self.badge.font = self.badgeFont;
- self.badge.text = (value > self.badgeMaximumBadgeNumber ?
- [NSString stringWithFormat:@"%@+", @(self.badgeMaximumBadgeNumber)] :
- [NSString stringWithFormat:@"%@", @(value)]);
- [self adjustLabelWidth:self.badge];
- CGRect frame = self.badge.frame;
- frame.size.width += 4;
- frame.size.height += 4;
- if(CGRectGetWidth(frame) < CGRectGetHeight(frame)) {
- frame.size.width = CGRectGetHeight(frame);
- }
- self.badge.frame = frame;
- self.badge.center = CGPointMake(CGRectGetWidth(self.frame) + 2 + self.badgeCenterOffset.x, self.badgeCenterOffset.y);
- self.badge.layer.cornerRadius = CGRectGetHeight(self.badge.frame) / 2;
- }
- //lazy loading
- - (void)badgeInit
- {
- if (self.badgeBgColor == nil) {
- self.badgeBgColor = [UIColor redColor];
- }
- if (self.badgeTextColor == nil) {
- self.badgeTextColor = [UIColor whiteColor];
- }
-
- if (nil == self.badge) {
- CGFloat redotWidth = kWZLBadgeDefaultRedDotRadius *2;
- CGRect frm = CGRectMake(CGRectGetWidth(self.frame), -redotWidth, redotWidth, redotWidth);
- self.badge = [[UILabel alloc] initWithFrame:frm];
- self.badge.textAlignment = NSTextAlignmentCenter;
- self.badge.center = CGPointMake(CGRectGetWidth(self.frame) + 2 + self.badgeCenterOffset.x, self.badgeCenterOffset.y);
- self.badge.backgroundColor = self.badgeBgColor;
- self.badge.textColor = self.badgeTextColor;
- self.badge.text = @"";
- self.badge.tag = WBadgeStyleRedDot;//red dot by default
- self.badge.layer.cornerRadius = CGRectGetWidth(self.badge.frame) / 2;
- self.badge.layer.masksToBounds = YES;//very important
- self.badge.hidden = NO;
- [self addSubview:self.badge];
- [self bringSubviewToFront:self.badge];
- }
- }
- #pragma mark -- other private methods
- - (void)adjustLabelWidth:(UILabel *)label
- {
- [label setNumberOfLines:0];
- NSString *s = label.text;
- UIFont *font = [label font];
- CGSize size = CGSizeMake(320,2000);
- CGSize labelsize;
- if (![s respondsToSelector:@selector(boundingRectWithSize:options:attributes:context:)]) {
- #pragma clang diagnostic push
- #pragma clang diagnostic ignored "-Wdeprecated-declarations"
- labelsize = [s sizeWithFont:font constrainedToSize:size lineBreakMode:NSLineBreakByWordWrapping];
- #pragma clang diagnostic pop
-
- } else {
- NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
- [style setLineBreakMode:NSLineBreakByWordWrapping];
-
- labelsize = [s boundingRectWithSize:size
- options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
- attributes:@{ NSFontAttributeName:font, NSParagraphStyleAttributeName : style}
- context:nil].size;
- }
- CGRect frame = label.frame;
- frame.size = CGSizeMake(ceilf(labelsize.width), ceilf(labelsize.height));
- [label setFrame:frame];
- }
- #pragma mark -- animation
- //if u want to add badge animation type, follow steps bellow:
- //1. go to definition of WBadgeAnimType and add new type
- //2. go to category of CAAnimation+WAnimation to add new animation interface
- //3. call that new interface here
- - (void)beginAnimation
- {
- switch(self.aniType) {
- case WBadgeAnimTypeBreathe:
- [self.badge.layer addAnimation:[CAAnimation opacityForever_Animation:1.4]
- forKey:kBadgeBreatheAniKey];
- break;
- case WBadgeAnimTypeShake:
- [self.badge.layer addAnimation:[CAAnimation shake_AnimationRepeatTimes:CGFLOAT_MAX
- durTimes:1
- forObj:self.badge.layer]
- forKey:kBadgeShakeAniKey];
- break;
- case WBadgeAnimTypeScale:
- [self.badge.layer addAnimation:[CAAnimation scaleFrom:1.4
- toScale:0.6
- durTimes:1
- rep:MAXFLOAT]
- forKey:kBadgeScaleAniKey];
- break;
- case WBadgeAnimTypeBounce:
- [self.badge.layer addAnimation:[CAAnimation bounce_AnimationRepeatTimes:CGFLOAT_MAX
- durTimes:1
- forObj:self.badge.layer]
- forKey:kBadgeBounceAniKey];
- break;
- case WBadgeAnimTypeNone:
- default:
- break;
- }
- }
- - (void)removeAnimation
- {
- if (self.badge) {
- [self.badge.layer removeAllAnimations];
- }
- }
- #pragma mark -- setter/getter
- - (UILabel *)badge
- {
- return objc_getAssociatedObject(self, &badgeLabelKey);
- }
- - (void)setBadge:(UILabel *)label
- {
- objc_setAssociatedObject(self, &badgeLabelKey, label, OBJC_ASSOCIATION_RETAIN);
- }
- - (UIFont *)badgeFont
- {
- id font = objc_getAssociatedObject(self, &badgeFontKey);
- return font == nil ? kWZLBadgeDefaultFont : font;
- }
- - (void)setBadgeFont:(UIFont *)badgeFont
- {
- objc_setAssociatedObject(self, &badgeFontKey, badgeFont, OBJC_ASSOCIATION_RETAIN);
- if (!self.badge) {
- [self badgeInit];
- }
- self.badge.font = badgeFont;
- }
- - (UIColor *)badgeBgColor
- {
- return objc_getAssociatedObject(self, &badgeBgColorKey);
- }
- - (void)setBadgeBgColor:(UIColor *)badgeBgColor
- {
- objc_setAssociatedObject(self, &badgeBgColorKey, badgeBgColor, OBJC_ASSOCIATION_RETAIN);
- if (!self.badge) {
- [self badgeInit];
- }
- self.badge.backgroundColor = badgeBgColor;
- }
- - (UIColor *)badgeTextColor
- {
- return objc_getAssociatedObject(self, &badgeTextColorKey);
- }
- - (void)setBadgeTextColor:(UIColor *)badgeTextColor
- {
- objc_setAssociatedObject(self, &badgeTextColorKey, badgeTextColor, OBJC_ASSOCIATION_RETAIN);
- if (!self.badge) {
- [self badgeInit];
- }
- self.badge.textColor = badgeTextColor;
- }
- - (WBadgeAnimType)aniType
- {
- id obj = objc_getAssociatedObject(self, &badgeAniTypeKey);
- if(obj != nil && [obj isKindOfClass:[NSNumber class]])
- {
- return [obj integerValue];
- }
- else
- return WBadgeAnimTypeNone;
- }
- - (void)setAniType:(WBadgeAnimType)aniType
- {
- NSNumber *numObj = @(aniType);
- objc_setAssociatedObject(self, &badgeAniTypeKey, numObj, OBJC_ASSOCIATION_RETAIN);
- if (!self.badge) {
- [self badgeInit];
- }
- [self removeAnimation];
- [self beginAnimation];
- }
- - (CGRect)badgeFrame
- {
- id obj = objc_getAssociatedObject(self, &badgeFrameKey);
- if (obj != nil && [obj isKindOfClass:[NSDictionary class]] && [obj count] == 4) {
- CGFloat x = [obj[@"x"] floatValue];
- CGFloat y = [obj[@"y"] floatValue];
- CGFloat width = [obj[@"width"] floatValue];
- CGFloat height = [obj[@"height"] floatValue];
- return CGRectMake(x, y, width, height);
- } else
- return CGRectZero;
- }
- - (void)setBadgeFrame:(CGRect)badgeFrame
- {
- NSDictionary *frameInfo = @{@"x" : @(badgeFrame.origin.x), @"y" : @(badgeFrame.origin.y),
- @"width" : @(badgeFrame.size.width), @"height" : @(badgeFrame.size.height)};
- objc_setAssociatedObject(self, &badgeFrameKey, frameInfo, OBJC_ASSOCIATION_RETAIN);
- if (!self.badge) {
- [self badgeInit];
- }
- self.badge.frame = badgeFrame;
- }
- - (CGPoint)badgeCenterOffset
- {
- id obj = objc_getAssociatedObject(self, &badgeCenterOffsetKey);
- if (obj != nil && [obj isKindOfClass:[NSDictionary class]] && [obj count] == 2) {
- CGFloat x = [obj[@"x"] floatValue];
- CGFloat y = [obj[@"y"] floatValue];
- return CGPointMake(x, y);
- } else
- return CGPointZero;
- }
- - (void)setBadgeCenterOffset:(CGPoint)badgeCenterOff
- {
- NSDictionary *cenerInfo = @{@"x" : @(badgeCenterOff.x), @"y" : @(badgeCenterOff.y)};
- objc_setAssociatedObject(self, &badgeCenterOffsetKey, cenerInfo, OBJC_ASSOCIATION_RETAIN);
- if (!self.badge) {
- [self badgeInit];
- }
- self.badge.center = CGPointMake(CGRectGetWidth(self.frame) + 2 + badgeCenterOff.x, badgeCenterOff.y);
- }
- //badgeRadiusKey
- - (void)setBadgeRadius:(CGFloat)badgeRadius {
- objc_setAssociatedObject(self, &badgeRadiusKey, [NSNumber numberWithFloat:badgeRadius], OBJC_ASSOCIATION_RETAIN);
- if (!self.badge) {
- [self badgeInit];
- }
- }
- - (CGFloat)badgeRadius {
- return [objc_getAssociatedObject(self, &badgeRadiusKey) floatValue];
- }
- - (NSInteger)badgeMaximumBadgeNumber {
- id obj = objc_getAssociatedObject(self, &badgeMaximumBadgeNumberKey);
- if(obj != nil && [obj isKindOfClass:[NSNumber class]])
- {
- return [obj integerValue];
- }
- else
- return kWZLBadgeDefaultMaximumBadgeNumber;
- }
- - (void)setBadgeMaximumBadgeNumber:(NSInteger)badgeMaximumBadgeNumber {
- NSNumber *numObj = @(badgeMaximumBadgeNumber);
- objc_setAssociatedObject(self, &badgeMaximumBadgeNumberKey, numObj, OBJC_ASSOCIATION_RETAIN);
- if (!self.badge) {
- [self badgeInit];
- }
- }
- @end
|