diff --git a/Example/JSBadgeView/Images.xcassets/AppIcon.appiconset/Contents.json b/Example/JSBadgeView/Images.xcassets/AppIcon.appiconset/Contents.json index f697f61..36d2c80 100644 --- a/Example/JSBadgeView/Images.xcassets/AppIcon.appiconset/Contents.json +++ b/Example/JSBadgeView/Images.xcassets/AppIcon.appiconset/Contents.json @@ -5,16 +5,31 @@ "size" : "29x29", "scale" : "2x" }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, { "idiom" : "iphone", "size" : "40x40", "scale" : "2x" }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, { "idiom" : "iphone", "size" : "60x60", "scale" : "2x" }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + }, { "idiom" : "ipad", "size" : "29x29", @@ -50,4 +65,4 @@ "version" : 1, "author" : "xcode" } -} +} \ No newline at end of file diff --git a/Example/JSBadgeView/JSViewController.m b/Example/JSBadgeView/JSViewController.m index 24e2c76..42f70ab 100644 --- a/Example/JSBadgeView/JSViewController.m +++ b/Example/JSBadgeView/JSViewController.m @@ -20,7 +20,7 @@ #import -#define kNumBadges 100 +#define kNumBadges 120 #define kViewBackgroundColor [UIColor colorWithRed:0.357 green:0.757 blue:0.357 alpha:1] @@ -76,7 +76,9 @@ - (void)loadView JSBadgeView *badgeView = [[JSBadgeView alloc] initWithParentView:rectangle alignment:JSBadgeViewAlignmentTopRight]; badgeView.badgeText = [NSString stringWithFormat:@"%d", i]; - + if (i >= 100) { + badgeView.tinyMode = YES; + } [scrollView addSubview:rectangle]; [scrollView sendSubviewToBack:rectangle]; diff --git a/Example/Podfile.lock b/Example/Podfile.lock index 42ed2da..3144819 100644 --- a/Example/Podfile.lock +++ b/Example/Podfile.lock @@ -1,6 +1,6 @@ PODS: - Expecta (1.0.6) - - JSBadgeView (1.4.1) + - JSBadgeView (2.0.0) - Specta (1.0.7) DEPENDENCIES: @@ -9,7 +9,7 @@ DEPENDENCIES: - Specta SPEC REPOS: - https://github.com/CocoaPods/Specs.git: + https://github.com/cocoapods/specs.git: - Expecta - Specta @@ -19,9 +19,9 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: Expecta: 3b6bd90a64b9a1dcb0b70aa0e10a7f8f631667d5 - JSBadgeView: 67b15e14438b19adc40ddc016d36b07016a68044 + JSBadgeView: 3dbfbaf6c580f5f8dc8d1283d826c94f2041b7c5 Specta: 3e1bd89c3517421982dc4d1c992503e48bd5fe66 PODFILE CHECKSUM: c814e0cbf7cb16d7dab3042bf5dc39c9d36b0d13 -COCOAPODS: 1.5.0 +COCOAPODS: 1.5.3 diff --git a/Pod/Classes/JSBadgeView.h b/Pod/Classes/JSBadgeView.h index 8128e9d..591aad2 100644 --- a/Pod/Classes/JSBadgeView.h +++ b/Pod/Classes/JSBadgeView.h @@ -92,6 +92,42 @@ typedef NS_ENUM(NSUInteger, JSBadgeViewAlignment) */ @property (nonatomic, assign) CGFloat badgeMinWidth UI_APPEARANCE_SELECTOR; +/** + * The margin add to the text left and right,both left and right use badgeViewTextSideMargin/2. + */ +@property (nonatomic,assign) CGFloat badgeViewTextSideMargin UI_APPEARANCE_SELECTOR; + +/** + * The corner radius use to the display rect. + */ +@property (nonatomic,assign) CGFloat badgeViewCornerRadius UI_APPEARANCE_SELECTOR; + +/** + * The height for the hold rect of text. + */ +@property (nonatomic,assign) CGFloat badgeViewHeight UI_APPEARANCE_SELECTOR; +/** + * shadow radius, if it > 0, we will draw a shadow. + */ +@property (nonatomic,assign) CGFloat badgeViewShadowRadius UI_APPEARANCE_SELECTOR; +/** + * will you prefer a backgroud image? it will auto scale to fit the badge size with the same radio. + */ +@property (nonatomic,strong) UIImage* badgeBackgroundImage UI_APPEARANCE_SELECTOR; +/** + * tiny mode,not show text,just a small cire. + */ +@property (nonatomic,assign) BOOL tinyMode UI_APPEARANCE_SELECTOR; +/** + * tiny mode's backgroud color. + */ +@property (nonatomic,strong) UIColor* tinyModeBackgroundColor UI_APPEARANCE_SELECTOR; + +/** + * tiny mode's radius. + */ +@property (nonatomic,assign) CGFloat badgeViewTinyRadius UI_APPEARANCE_SELECTOR; + /** * Optionally init using this method to have the badge automatically added to another view. */ diff --git a/Pod/Classes/JSBadgeView.m b/Pod/Classes/JSBadgeView.m index f36d347..67a0485 100644 --- a/Pod/Classes/JSBadgeView.m +++ b/Pod/Classes/JSBadgeView.m @@ -63,6 +63,15 @@ + (void)applyStyle badgeViewAppearanceProxy.badgeShadowColor = UIColor.clearColor; badgeViewAppearanceProxy.badgeStrokeWidth = 0.0f; badgeViewAppearanceProxy.badgeStrokeColor = badgeViewAppearanceProxy.badgeBackgroundColor; + + badgeViewAppearanceProxy.badgeViewShadowRadius = 1.0f; + badgeViewAppearanceProxy.badgeViewHeight = 16.0f; + badgeViewAppearanceProxy.badgeViewTextSideMargin = 8.0f; + badgeViewAppearanceProxy.badgeViewCornerRadius = 10.0f; + badgeViewAppearanceProxy.tinyMode = NO; + badgeViewAppearanceProxy.tinyModeBackgroundColor = UIColor.redColor; + badgeViewAppearanceProxy.badgeViewTinyRadius = 5.0f; + } + (void)initialize @@ -84,6 +93,21 @@ - (id)initWithParentView:(UIView *)parentView alignment:(JSBadgeViewAlignment)al return self; } +-(void) setTinyMode:(BOOL)tinyMode +{ + if ( tinyMode == self.tinyMode) { + return; + } + _tinyMode = tinyMode; + [self setNeedsLayout]; +} + +-(void)setBadgeBackgroundImage:(UIImage *)badgeBackgroundImage +{ + _badgeBackgroundImage = badgeBackgroundImage; + [self setNeedsLayout]; +} + #pragma mark - Layout - (CGFloat)marginToDrawInside @@ -94,19 +118,25 @@ - (CGFloat)marginToDrawInside - (void)layoutSubviews { [super layoutSubviews]; - + + CGRect newFrame = self.frame; - const CGRect superviewBounds = CGRectIsEmpty(_frameToPositionInRelationWith) ? self.superview.bounds : _frameToPositionInRelationWith; + const CGRect superviewBounds = CGRectIsEmpty(self.frameToPositionInRelationWith) ? self.superview.bounds : self.frameToPositionInRelationWith; const CGFloat textWidth = [self sizeOfTextForCurrentSettings].width; - + const CGFloat marginToDrawInside = [self marginToDrawInside]; - const CGFloat viewWidth = MAX(_badgeMinWidth, textWidth + JSBadgeViewTextSideMargin + (marginToDrawInside * 2)); - const CGFloat viewHeight = JSBadgeViewHeight + (marginToDrawInside * 2); + CGFloat viewWidth = MAX(self.badgeMinWidth, textWidth + self.badgeViewTextSideMargin + (marginToDrawInside * 2)); + CGFloat viewHeight = self.badgeViewHeight + (marginToDrawInside * 2); const CGFloat superviewWidth = superviewBounds.size.width; const CGFloat superviewHeight = superviewBounds.size.height; + if (self.tinyMode) { + viewWidth = 2*self.badgeViewTinyRadius; + viewHeight = viewWidth; + } + newFrame.size.width = MAX(viewWidth, viewHeight); newFrame.size.height = viewHeight; @@ -301,19 +331,51 @@ - (void)drawRect:(CGRect)rect const CGFloat marginToDrawInside = [self marginToDrawInside]; const CGRect rectToDraw = CGRectInset(rect, marginToDrawInside, marginToDrawInside); - UIBezierPath *borderPath = [UIBezierPath bezierPathWithRoundedRect:rectToDraw byRoundingCorners:(UIRectCorner)UIRectCornerAllCorners cornerRadii:CGSizeMake(JSBadgeViewCornerRadius, JSBadgeViewCornerRadius)]; + UIBezierPath *borderPath; + if (self.tinyMode) { + borderPath= [UIBezierPath bezierPathWithRoundedRect:rectToDraw byRoundingCorners:(UIRectCorner)UIRectCornerAllCorners cornerRadii:CGSizeMake(self.badgeViewTinyRadius+marginToDrawInside, self.badgeViewTinyRadius+marginToDrawInside)]; + } + else{ + borderPath= [UIBezierPath bezierPathWithRoundedRect:rectToDraw byRoundingCorners:(UIRectCorner)UIRectCornerAllCorners cornerRadii:CGSizeMake(self.badgeViewCornerRadius, self.badgeViewCornerRadius)]; + } + CGColorRef bgCGColor = self.tinyMode ? self.tinyModeBackgroundColor.CGColor : self.badgeBackgroundColor.CGColor; - /* Background and shadow */ - CGContextSaveGState(ctx); - { - CGContextAddPath(ctx, borderPath.CGPath); + if (nil == self.badgeBackgroundImage) { + CGContextSetFillColorWithColor(ctx, bgCGColor); + /* Background and shadow */ + CGContextSaveGState(ctx); + { + CGContextAddPath(ctx, borderPath.CGPath); + if (!self.tinyMode && self.badgeViewShadowRadius > 0 ) { + CGContextSetShadowWithColor(ctx, self.badgeShadowSize, self.badgeViewShadowRadius, self.badgeShadowColor.CGColor); + } + + CGContextDrawPath(ctx, kCGPathFill); + } + CGContextRestoreGState(ctx); + + } + else{ + + CGFloat width = self.badgeBackgroundImage.size.width; + CGFloat height = self.badgeBackgroundImage.size.height; + + float verticalRadio = rectToDraw.size.height*1.0/height; + float horizontalRadio = rectToDraw.size.width*1.0/width; - CGContextSetFillColorWithColor(ctx, self.badgeBackgroundColor.CGColor); - CGContextSetShadowWithColor(ctx, self.badgeShadowSize, JSBadgeViewShadowRadius, self.badgeShadowColor.CGColor); + float radio = 1; + radio = verticalRadio < horizontalRadio ? horizontalRadio : verticalRadio; + + CGRect displayRect = CGRectMake((rectToDraw.size.width - width*radio)/2.0f, + (rectToDraw.size.height-height*radio)/2.0f, + width*radio, + height*radio); + + [self.badgeBackgroundImage drawInRect:displayRect]; - CGContextDrawPath(ctx, kCGPathFill); } - CGContextRestoreGState(ctx); + + const BOOL colorForOverlayPresent = self.badgeOverlayColor && ![self.badgeOverlayColor isEqual:[UIColor clearColor]]; @@ -353,25 +415,34 @@ - (void)drawRect:(CGRect)rect } CGContextRestoreGState(ctx); + if (self.tinyMode) { + return; + } /* Text */ CGContextSaveGState(ctx); { CGContextSetFillColorWithColor(ctx, self.badgeTextColor.CGColor); - CGContextSetShadowWithColor(ctx, self.badgeTextShadowOffset, 1.0, self.badgeTextShadowColor.CGColor); + if (self.badgeViewShadowRadius > 0) { + CGContextSetShadowWithColor(ctx, self.badgeTextShadowOffset, 1.0, self.badgeTextShadowColor.CGColor); + } CGRect textFrame = rectToDraw; const CGSize textSize = [self sizeOfTextForCurrentSettings]; textFrame.size.height = textSize.height; - textFrame.origin.y = rectToDraw.origin.y + floorf((rectToDraw.size.height - textFrame.size.height) / 2.0f); - + textFrame.origin.y = rectToDraw.origin.y + ceilf((rectToDraw.size.height - textFrame.size.height) / 2.0f); + + NSMutableParagraphStyle *textStyle = [[NSMutableParagraphStyle defaultParagraphStyle] mutableCopy]; + textStyle.lineBreakMode = NSLineBreakByClipping; + textStyle.alignment = NSTextAlignmentCenter; + JSBadgeViewSilenceDeprecatedMethodStart(); [self.badgeText drawInRect:textFrame - withFont:self.badgeTextFont - lineBreakMode:NSLineBreakByClipping - alignment:NSTextAlignmentCenter]; + withAttributes:@{NSFontAttributeName:self.badgeTextFont, + NSParagraphStyleAttributeName: textStyle}]; JSBadgeViewSilenceDeprecatedMethodEnd(); + } CGContextRestoreGState(ctx); }