Skip to content

Commit 3104b6c

Browse files
committed
Merge pull request #10 from JaviSoto/feature/ios7
iOS 7 flat style
2 parents 70c41d9 + 0e7d0a6 commit 3104b6c

File tree

3 files changed

+127
-58
lines changed

3 files changed

+127
-58
lines changed

JSBadgeView/JSBadgeView.h

+16-6
Original file line numberDiff line numberDiff line change
@@ -52,33 +52,43 @@ typedef NS_ENUM(NSUInteger, JSBadgeViewAlignment)
5252
@property (nonatomic, strong) UIColor *badgeBackgroundColor UI_APPEARANCE_SELECTOR;
5353

5454
/**
55-
* @discussion color of the overlay circle at the top. Default is semi-transparent white.
55+
* Color of the overlay circle at the top. Default is semi-transparent white.
5656
*/
5757
@property (nonatomic, strong) UIColor *badgeOverlayColor UI_APPEARANCE_SELECTOR;
5858

5959
/**
60-
* @discussion color of the badge shadow. Default is semi-transparent black.
60+
* Color of the badge shadow. Default is semi-transparent black.
6161
*/
6262
@property (nonatomic, strong) UIColor *badgeShadowColor UI_APPEARANCE_SELECTOR;
6363

6464
/**
65-
* @discussion color of the circle around the badge. Default is white.
65+
* Offset of the badge shadow. Default is 3.0 points down.
66+
*/
67+
@property (nonatomic, assign) CGSize badgeShadowSize UI_APPEARANCE_SELECTOR;
68+
69+
/**
70+
* Width of the circle around the badge. Default is 2.0 points.
71+
*/
72+
@property (nonatomic, assign) CGFloat badgeStrokeWidth UI_APPEARANCE_SELECTOR;
73+
74+
/**
75+
* Color of the circle around the badge. Default is white.
6676
*/
6777
@property (nonatomic, strong) UIColor *badgeStrokeColor UI_APPEARANCE_SELECTOR;
6878

6979
/**
70-
* @discussion allows to shift the badge by x and y points.
80+
* Allows to shift the badge by x and y points.
7181
*/
7282
@property (nonatomic, assign) CGPoint badgePositionAdjustment UI_APPEARANCE_SELECTOR;
7383

7484
/**
75-
* @discussion (optional) If not provided, the superview frame is used.
7685
* You can use this to position the view if you're drawing it using drawRect instead of `-addSubview:`
86+
* (optional) If not provided, the superview frame is used.
7787
*/
7888
@property (nonatomic, assign) CGRect frameToPositionInRelationWith UI_APPEARANCE_SELECTOR;
7989

8090
/**
81-
* @discussion optionally init using this method to have the badge automatically added to another view.
91+
* Optionally init using this method to have the badge automatically added to another view.
8292
*/
8393
- (id)initWithParentView:(UIView *)parentView alignment:(JSBadgeViewAlignment)alignment;
8494

JSBadgeView/JSBadgeView.m

+105-50
Original file line numberDiff line numberDiff line change
@@ -28,48 +28,90 @@ of this software and associated documentation files (the "Software"), to deal
2828
#error JSBadgeView must be compiled with ARC.
2929
#endif
3030

31-
#define kDefaultBadgeTextColor [UIColor whiteColor]
32-
#define kDefaultBadgeBackgroundColor [UIColor redColor]
33-
#define kDefaultOverlayColor [UIColor colorWithWhite:1.0f alpha:0.3]
31+
static const CGFloat JSBadgeViewShadowRadius = 1.0f;
32+
static const CGFloat JSBadgeViewHeight = 16.0f;
33+
static const CGFloat JSBadgeViewTextSideMargin = 8.0f;
34+
static const CGFloat JSBadgeViewCornerRadius = 10.0f;
3435

35-
#define kDefaultBadgeTextFont [UIFont boldSystemFontOfSize:[UIFont systemFontSize]]
36-
37-
#define kDefaultBadgeShadowColor [UIColor clearColor]
38-
39-
#define kDefaultBadgeStrokeColor [UIColor whiteColor]
40-
#define kBadgeStrokeWidth 2.0f
36+
// Thanks to Peter Steinberger: https://gist.github.com/steipete/6526860
37+
static BOOL JSBadgeViewIsUIKitFlatMode(void)
38+
{
39+
static BOOL isUIKitFlatMode = NO;
40+
static dispatch_once_t onceToken;
41+
dispatch_once(&onceToken, ^{
42+
#ifndef kCFCoreFoundationVersionNumber_iOS_7_0
43+
#define kCFCoreFoundationVersionNumber_iOS_7_0 847.2
44+
#endif
4145

42-
#define kMarginToDrawInside (kBadgeStrokeWidth * 2)
46+
if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_7_0)
47+
{
48+
// If your app is running in legacy mode, tintColor will be nil - else it must be set to some color.
49+
if (UIApplication.sharedApplication.keyWindow)
50+
{
51+
isUIKitFlatMode = [UIApplication.sharedApplication.keyWindow performSelector:@selector(tintColor)] != nil;
52+
}
53+
else
54+
{
55+
// Possible that we're called early on (e.g. when used in a Storyboard). Adapt and use a temporary window.
56+
isUIKitFlatMode = [[[UIWindow alloc] init] performSelector:@selector(tintColor)] != nil;
57+
}
58+
}
59+
});
4360

44-
#define kShadowOffset CGSizeMake(0.0f, 3.0f)
45-
#define kShadowOpacity 0.4f
46-
#define kDefaultShadowColor [UIColor colorWithWhite:0.0f alpha:kShadowOpacity]
47-
#define kShadowRadius 1.0f
61+
return isUIKitFlatMode;
62+
}
4863

49-
#define kBadgeHeight 16.0f
50-
#define kBadgeTextSideMargin 8.0f
64+
@implementation JSBadgeView
5165

52-
#define kBadgeCornerRadius 10.0f
66+
+ (void)applyCommonStyle
67+
{
68+
JSBadgeView *badgeViewAppearanceProxy = JSBadgeView.appearance;
5369

54-
#define kDefaultBadgeAlignment JSBadgeViewAlignmentTopRight
70+
badgeViewAppearanceProxy.backgroundColor = UIColor.clearColor;
71+
badgeViewAppearanceProxy.badgeAlignment = JSBadgeViewAlignmentTopRight;
72+
badgeViewAppearanceProxy.badgeBackgroundColor = UIColor.redColor;
73+
badgeViewAppearanceProxy.badgeTextFont = [UIFont boldSystemFontOfSize:UIFont.systemFontSize];
74+
badgeViewAppearanceProxy.badgeTextColor = UIColor.whiteColor;
75+
}
5576

56-
@implementation JSBadgeView
77+
+ (void)applyLegacyStyle
78+
{
79+
JSBadgeView *badgeViewAppearanceProxy = JSBadgeView.appearance;
80+
81+
badgeViewAppearanceProxy.badgeOverlayColor = [UIColor colorWithWhite:1.0f alpha:0.3];
82+
badgeViewAppearanceProxy.badgeTextShadowColor = UIColor.clearColor;
83+
badgeViewAppearanceProxy.badgeShadowColor = [UIColor colorWithWhite:0.0f alpha:0.4f];
84+
badgeViewAppearanceProxy.badgeShadowSize = CGSizeMake(0.0f, 3.0f);
85+
badgeViewAppearanceProxy.badgeStrokeWidth = 2.0f;
86+
badgeViewAppearanceProxy.badgeStrokeColor = UIColor.whiteColor;
87+
}
5788

58-
- (void)awakeFromNib
89+
+ (void)applyIOS7Style
5990
{
60-
[super awakeFromNib];
91+
JSBadgeView *badgeViewAppearanceProxy = JSBadgeView.appearance;
6192

62-
[self _init];
93+
badgeViewAppearanceProxy.badgeOverlayColor = UIColor.clearColor;
94+
badgeViewAppearanceProxy.badgeTextShadowColor = UIColor.clearColor;
95+
badgeViewAppearanceProxy.badgeShadowColor = UIColor.clearColor;
96+
badgeViewAppearanceProxy.badgeStrokeWidth = 0.0f;
97+
badgeViewAppearanceProxy.badgeStrokeColor = badgeViewAppearanceProxy.badgeBackgroundColor;
6398
}
6499

65-
- (id)initWithFrame:(CGRect)frame
100+
+ (void)initialize
66101
{
67-
if ((self = [super initWithFrame:frame]))
102+
if (self == JSBadgeView.class)
68103
{
69-
[self _init];
70-
}
104+
[self applyCommonStyle];
71105

72-
return self;
106+
if (JSBadgeViewIsUIKitFlatMode())
107+
{
108+
[self applyIOS7Style];
109+
}
110+
else
111+
{
112+
[self applyLegacyStyle];
113+
}
114+
}
73115
}
74116

75117
- (id)initWithParentView:(UIView *)parentView alignment:(JSBadgeViewAlignment)alignment
@@ -83,23 +125,13 @@ - (id)initWithParentView:(UIView *)parentView alignment:(JSBadgeViewAlignment)al
83125
return self;
84126
}
85127

86-
- (void)_init
87-
{
88-
self.backgroundColor = [UIColor clearColor];
89-
90-
_badgeAlignment = kDefaultBadgeAlignment;
91-
92-
_badgeBackgroundColor = kDefaultBadgeBackgroundColor;
93-
_badgeOverlayColor = kDefaultOverlayColor;
94-
_badgeTextColor = kDefaultBadgeTextColor;
95-
_badgeTextShadowColor = kDefaultBadgeShadowColor;
96-
_badgeTextFont = kDefaultBadgeTextFont;
97-
_badgeShadowColor = kDefaultBadgeShadowColor;
98-
_badgeStrokeColor = kDefaultBadgeStrokeColor;
99-
}
100-
101128
#pragma mark - Layout
102129

130+
- (CGFloat)marginToDrawInside
131+
{
132+
return self.badgeStrokeWidth * 2.0f;
133+
}
134+
103135
- (void)layoutSubviews
104136
{
105137
[super layoutSubviews];
@@ -108,9 +140,10 @@ - (void)layoutSubviews
108140
const CGRect superviewBounds = CGRectIsEmpty(_frameToPositionInRelationWith) ? self.superview.bounds : _frameToPositionInRelationWith;
109141

110142
const CGFloat textWidth = [self sizeOfTextForCurrentSettings].width;
111-
112-
const CGFloat viewWidth = textWidth + kBadgeTextSideMargin + (kMarginToDrawInside * 2);
113-
const CGFloat viewHeight = kBadgeHeight + (kMarginToDrawInside * 2);
143+
144+
const CGFloat marginToDrawInside = [self marginToDrawInside];
145+
const CGFloat viewWidth = textWidth + JSBadgeViewTextSideMargin + (marginToDrawInside * 2);
146+
const CGFloat viewHeight = JSBadgeViewHeight + (marginToDrawInside * 2);
114147

115148
const CGFloat superviewWidth = superviewBounds.size.width;
116149
const CGFloat superviewHeight = superviewBounds.size.height;
@@ -250,6 +283,17 @@ - (void)setBadgeBackgroundColor:(UIColor *)badgeBackgroundColor
250283
}
251284
}
252285

286+
- (void)setBadgeStrokeWidth:(CGFloat)badgeStrokeWidth
287+
{
288+
if (badgeStrokeWidth != _badgeStrokeWidth)
289+
{
290+
_badgeStrokeWidth = badgeStrokeWidth;
291+
292+
[self setNeedsLayout];
293+
[self setNeedsDisplay];
294+
}
295+
}
296+
253297
- (void)setBadgeStrokeColor:(UIColor *)badgeStrokeColor
254298
{
255299
if (badgeStrokeColor != _badgeStrokeColor)
@@ -270,6 +314,16 @@ - (void)setBadgeShadowColor:(UIColor *)badgeShadowColor
270314
}
271315
}
272316

317+
- (void)setBadgeShadowSize:(CGSize)badgeShadowSize
318+
{
319+
if (!CGSizeEqualToSize(badgeShadowSize, _badgeShadowSize))
320+
{
321+
_badgeShadowSize = badgeShadowSize;
322+
323+
[self setNeedsDisplay];
324+
}
325+
}
326+
273327
#pragma mark - Drawing
274328

275329
- (void)drawRect:(CGRect)rect
@@ -279,18 +333,19 @@ - (void)drawRect:(CGRect)rect
279333
if (anyTextToDraw)
280334
{
281335
CGContextRef ctx = UIGraphicsGetCurrentContext();
336+
337+
const CGFloat marginToDrawInside = [self marginToDrawInside];
338+
const CGRect rectToDraw = CGRectInset(rect, marginToDrawInside, marginToDrawInside);
282339

283-
const CGRect rectToDraw = CGRectInset(rect, kMarginToDrawInside, kMarginToDrawInside);
284-
285-
UIBezierPath *borderPath = [UIBezierPath bezierPathWithRoundedRect:rectToDraw byRoundingCorners:(UIRectCorner)UIRectCornerAllCorners cornerRadii:CGSizeMake(kBadgeCornerRadius, kBadgeCornerRadius)];
340+
UIBezierPath *borderPath = [UIBezierPath bezierPathWithRoundedRect:rectToDraw byRoundingCorners:(UIRectCorner)UIRectCornerAllCorners cornerRadii:CGSizeMake(JSBadgeViewCornerRadius, JSBadgeViewCornerRadius)];
286341

287342
/* Background and shadow */
288343
CGContextSaveGState(ctx);
289344
{
290345
CGContextAddPath(ctx, borderPath.CGPath);
291346

292347
CGContextSetFillColorWithColor(ctx, self.badgeBackgroundColor.CGColor);
293-
CGContextSetShadowWithColor(ctx, kShadowOffset, kShadowRadius, self.badgeShadowColor.CGColor);
348+
CGContextSetShadowWithColor(ctx, self.badgeShadowSize, JSBadgeViewShadowRadius, self.badgeShadowColor.CGColor);
294349

295350
CGContextDrawPath(ctx, kCGPathFill);
296351
}
@@ -327,7 +382,7 @@ - (void)drawRect:(CGRect)rect
327382
{
328383
CGContextAddPath(ctx, borderPath.CGPath);
329384

330-
CGContextSetLineWidth(ctx, kBadgeStrokeWidth);
385+
CGContextSetLineWidth(ctx, self.badgeStrokeWidth);
331386
CGContextSetStrokeColorWithColor(ctx, self.badgeStrokeColor.CGColor);
332387

333388
CGContextDrawPath(ctx, kCGPathStroke);

README.md

+6-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ Very optimized for performance: drawn entirely using CoreGraphics.
55

66
<img src="http://f.cl.ly/items/1L3k0z0a3X3i353M1G0h/JSBadgeView.png" />
77

8+
iOS 7 style:
9+
10+
<img src="http://cl.ly/image/3G3J2k3n133W/JSBadgeView-iOS7.png" />
11+
812
## Usage
913
- Clone the repository:
1014

@@ -30,14 +34,14 @@ badgeView.badgeText = @"3";
3034
- Check the header file for all the things you can customize.
3135
3236
## [CocoaPods](http://cocoapods.org/):
33-
- Add `pod 'JSBadgeView', '~> 1.2.0'` to your `Podfile`.
37+
- Add `pod 'JSBadgeView', '~> 1.3.0'` to your `Podfile`.
3438
- You're done!
3539
3640
## `UIAppearance`
3741
- You can customize all `JSBadgeView`s in your application, or the ones that are subviews of a specific type of view, using `UIAppearance`. Example:
3842
3943
```objc
40-
[[JSBadgeView appearance] setBadgeBackgroundColor:[UIColor blackColor]];
44+
[[JSBadgeView appearance] setBadgeBackgroundColor:UIColor.blackColor];
4145
[[JSBadgeView appearance] setBadgeAlignment:@(JSBadgeViewAlignmentTopRight)];
4246
```
4347

0 commit comments

Comments
 (0)