Skip to content

Commit

Permalink
Merge pull request #10 from JaviSoto/feature/ios7
Browse files Browse the repository at this point in the history
iOS 7 flat style
  • Loading branch information
JaviSoto committed Oct 1, 2013
2 parents 70c41d9 + 0e7d0a6 commit 3104b6c
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 58 deletions.
22 changes: 16 additions & 6 deletions JSBadgeView/JSBadgeView.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,33 +52,43 @@ typedef NS_ENUM(NSUInteger, JSBadgeViewAlignment)
@property (nonatomic, strong) UIColor *badgeBackgroundColor UI_APPEARANCE_SELECTOR;

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

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

/**
* @discussion color of the circle around the badge. Default is white.
* Offset of the badge shadow. Default is 3.0 points down.
*/
@property (nonatomic, assign) CGSize badgeShadowSize UI_APPEARANCE_SELECTOR;

/**
* Width of the circle around the badge. Default is 2.0 points.
*/
@property (nonatomic, assign) CGFloat badgeStrokeWidth UI_APPEARANCE_SELECTOR;

/**
* Color of the circle around the badge. Default is white.
*/
@property (nonatomic, strong) UIColor *badgeStrokeColor UI_APPEARANCE_SELECTOR;

/**
* @discussion allows to shift the badge by x and y points.
* Allows to shift the badge by x and y points.
*/
@property (nonatomic, assign) CGPoint badgePositionAdjustment UI_APPEARANCE_SELECTOR;

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

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

Expand Down
155 changes: 105 additions & 50 deletions JSBadgeView/JSBadgeView.m
Original file line number Diff line number Diff line change
Expand Up @@ -28,48 +28,90 @@ of this software and associated documentation files (the "Software"), to deal
#error JSBadgeView must be compiled with ARC.
#endif

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

#define kDefaultBadgeTextFont [UIFont boldSystemFontOfSize:[UIFont systemFontSize]]

#define kDefaultBadgeShadowColor [UIColor clearColor]

#define kDefaultBadgeStrokeColor [UIColor whiteColor]
#define kBadgeStrokeWidth 2.0f
// Thanks to Peter Steinberger: https://gist.github.com/steipete/6526860
static BOOL JSBadgeViewIsUIKitFlatMode(void)
{
static BOOL isUIKitFlatMode = NO;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
#ifndef kCFCoreFoundationVersionNumber_iOS_7_0
#define kCFCoreFoundationVersionNumber_iOS_7_0 847.2
#endif

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

#define kShadowOffset CGSizeMake(0.0f, 3.0f)
#define kShadowOpacity 0.4f
#define kDefaultShadowColor [UIColor colorWithWhite:0.0f alpha:kShadowOpacity]
#define kShadowRadius 1.0f
return isUIKitFlatMode;
}

#define kBadgeHeight 16.0f
#define kBadgeTextSideMargin 8.0f
@implementation JSBadgeView

#define kBadgeCornerRadius 10.0f
+ (void)applyCommonStyle
{
JSBadgeView *badgeViewAppearanceProxy = JSBadgeView.appearance;

#define kDefaultBadgeAlignment JSBadgeViewAlignmentTopRight
badgeViewAppearanceProxy.backgroundColor = UIColor.clearColor;
badgeViewAppearanceProxy.badgeAlignment = JSBadgeViewAlignmentTopRight;
badgeViewAppearanceProxy.badgeBackgroundColor = UIColor.redColor;
badgeViewAppearanceProxy.badgeTextFont = [UIFont boldSystemFontOfSize:UIFont.systemFontSize];
badgeViewAppearanceProxy.badgeTextColor = UIColor.whiteColor;
}

@implementation JSBadgeView
+ (void)applyLegacyStyle
{
JSBadgeView *badgeViewAppearanceProxy = JSBadgeView.appearance;

badgeViewAppearanceProxy.badgeOverlayColor = [UIColor colorWithWhite:1.0f alpha:0.3];
badgeViewAppearanceProxy.badgeTextShadowColor = UIColor.clearColor;
badgeViewAppearanceProxy.badgeShadowColor = [UIColor colorWithWhite:0.0f alpha:0.4f];
badgeViewAppearanceProxy.badgeShadowSize = CGSizeMake(0.0f, 3.0f);
badgeViewAppearanceProxy.badgeStrokeWidth = 2.0f;
badgeViewAppearanceProxy.badgeStrokeColor = UIColor.whiteColor;
}

- (void)awakeFromNib
+ (void)applyIOS7Style
{
[super awakeFromNib];
JSBadgeView *badgeViewAppearanceProxy = JSBadgeView.appearance;

[self _init];
badgeViewAppearanceProxy.badgeOverlayColor = UIColor.clearColor;
badgeViewAppearanceProxy.badgeTextShadowColor = UIColor.clearColor;
badgeViewAppearanceProxy.badgeShadowColor = UIColor.clearColor;
badgeViewAppearanceProxy.badgeStrokeWidth = 0.0f;
badgeViewAppearanceProxy.badgeStrokeColor = badgeViewAppearanceProxy.badgeBackgroundColor;
}

- (id)initWithFrame:(CGRect)frame
+ (void)initialize
{
if ((self = [super initWithFrame:frame]))
if (self == JSBadgeView.class)
{
[self _init];
}
[self applyCommonStyle];

return self;
if (JSBadgeViewIsUIKitFlatMode())
{
[self applyIOS7Style];
}
else
{
[self applyLegacyStyle];
}
}
}

- (id)initWithParentView:(UIView *)parentView alignment:(JSBadgeViewAlignment)alignment
Expand All @@ -83,23 +125,13 @@ - (id)initWithParentView:(UIView *)parentView alignment:(JSBadgeViewAlignment)al
return self;
}

- (void)_init
{
self.backgroundColor = [UIColor clearColor];

_badgeAlignment = kDefaultBadgeAlignment;

_badgeBackgroundColor = kDefaultBadgeBackgroundColor;
_badgeOverlayColor = kDefaultOverlayColor;
_badgeTextColor = kDefaultBadgeTextColor;
_badgeTextShadowColor = kDefaultBadgeShadowColor;
_badgeTextFont = kDefaultBadgeTextFont;
_badgeShadowColor = kDefaultBadgeShadowColor;
_badgeStrokeColor = kDefaultBadgeStrokeColor;
}

#pragma mark - Layout

- (CGFloat)marginToDrawInside
{
return self.badgeStrokeWidth * 2.0f;
}

- (void)layoutSubviews
{
[super layoutSubviews];
Expand All @@ -108,9 +140,10 @@ - (void)layoutSubviews
const CGRect superviewBounds = CGRectIsEmpty(_frameToPositionInRelationWith) ? self.superview.bounds : _frameToPositionInRelationWith;

const CGFloat textWidth = [self sizeOfTextForCurrentSettings].width;

const CGFloat viewWidth = textWidth + kBadgeTextSideMargin + (kMarginToDrawInside * 2);
const CGFloat viewHeight = kBadgeHeight + (kMarginToDrawInside * 2);

const CGFloat marginToDrawInside = [self marginToDrawInside];
const CGFloat viewWidth = textWidth + JSBadgeViewTextSideMargin + (marginToDrawInside * 2);
const CGFloat viewHeight = JSBadgeViewHeight + (marginToDrawInside * 2);

const CGFloat superviewWidth = superviewBounds.size.width;
const CGFloat superviewHeight = superviewBounds.size.height;
Expand Down Expand Up @@ -250,6 +283,17 @@ - (void)setBadgeBackgroundColor:(UIColor *)badgeBackgroundColor
}
}

- (void)setBadgeStrokeWidth:(CGFloat)badgeStrokeWidth
{
if (badgeStrokeWidth != _badgeStrokeWidth)
{
_badgeStrokeWidth = badgeStrokeWidth;

[self setNeedsLayout];
[self setNeedsDisplay];
}
}

- (void)setBadgeStrokeColor:(UIColor *)badgeStrokeColor
{
if (badgeStrokeColor != _badgeStrokeColor)
Expand All @@ -270,6 +314,16 @@ - (void)setBadgeShadowColor:(UIColor *)badgeShadowColor
}
}

- (void)setBadgeShadowSize:(CGSize)badgeShadowSize
{
if (!CGSizeEqualToSize(badgeShadowSize, _badgeShadowSize))
{
_badgeShadowSize = badgeShadowSize;

[self setNeedsDisplay];
}
}

#pragma mark - Drawing

- (void)drawRect:(CGRect)rect
Expand All @@ -279,18 +333,19 @@ - (void)drawRect:(CGRect)rect
if (anyTextToDraw)
{
CGContextRef ctx = UIGraphicsGetCurrentContext();

const CGFloat marginToDrawInside = [self marginToDrawInside];
const CGRect rectToDraw = CGRectInset(rect, marginToDrawInside, marginToDrawInside);

const CGRect rectToDraw = CGRectInset(rect, kMarginToDrawInside, kMarginToDrawInside);

UIBezierPath *borderPath = [UIBezierPath bezierPathWithRoundedRect:rectToDraw byRoundingCorners:(UIRectCorner)UIRectCornerAllCorners cornerRadii:CGSizeMake(kBadgeCornerRadius, kBadgeCornerRadius)];
UIBezierPath *borderPath = [UIBezierPath bezierPathWithRoundedRect:rectToDraw byRoundingCorners:(UIRectCorner)UIRectCornerAllCorners cornerRadii:CGSizeMake(JSBadgeViewCornerRadius, JSBadgeViewCornerRadius)];

/* Background and shadow */
CGContextSaveGState(ctx);
{
CGContextAddPath(ctx, borderPath.CGPath);

CGContextSetFillColorWithColor(ctx, self.badgeBackgroundColor.CGColor);
CGContextSetShadowWithColor(ctx, kShadowOffset, kShadowRadius, self.badgeShadowColor.CGColor);
CGContextSetShadowWithColor(ctx, self.badgeShadowSize, JSBadgeViewShadowRadius, self.badgeShadowColor.CGColor);

CGContextDrawPath(ctx, kCGPathFill);
}
Expand Down Expand Up @@ -327,7 +382,7 @@ - (void)drawRect:(CGRect)rect
{
CGContextAddPath(ctx, borderPath.CGPath);

CGContextSetLineWidth(ctx, kBadgeStrokeWidth);
CGContextSetLineWidth(ctx, self.badgeStrokeWidth);
CGContextSetStrokeColorWithColor(ctx, self.badgeStrokeColor.CGColor);

CGContextDrawPath(ctx, kCGPathStroke);
Expand Down
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ Very optimized for performance: drawn entirely using CoreGraphics.

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

iOS 7 style:

<img src="http://cl.ly/image/3G3J2k3n133W/JSBadgeView-iOS7.png" />

## Usage
- Clone the repository:

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

Expand Down

0 comments on commit 3104b6c

Please sign in to comment.