-
-
Save rsanchezsaez/ac620ce58bd6097207d8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// OEProgressIndicator.h | |
// Seene | |
// | |
// Copyright (c) 2014 Obvious Engine. All rights reserved. | |
// | |
#import <UIKit/UIKit.h> | |
IB_DESIGNABLE | |
@interface OEProgressIndicator : UIView | |
- (void)startAnimating; | |
- (void)stopAnimating; | |
- (void)showProgress:(CGFloat)progress; | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// OEProgressIndicator.m | |
// Seene | |
// | |
// Copyright (c) 2014 Obvious Engine. All rights reserved. | |
// | |
#import "OEProgressIndicator.h" | |
#import "OETheme.h" | |
const CGFloat OEProgressIndicatorRingThickness = 1.8; | |
@interface OEProgressIndicator () | |
@property (nonatomic, strong) CAShapeLayer *ringLayer; | |
@property (nonatomic, strong) CAShapeLayer *backgroundRingLayer; | |
@property (nonatomic) CGFloat ringRadius; | |
@property (strong, nonatomic) UIColor *ringForegroundColor; | |
@property (strong, nonatomic) UIColor *ringBackgroundColor; | |
@property (nonatomic, getter = isAnimating) BOOL animating; | |
@end | |
@implementation OEProgressIndicator | |
- (instancetype)initWithFrame:(CGRect)frame | |
{ | |
self = [super initWithFrame:frame]; | |
if (!self) { return nil; } | |
[self commonProgressIndicatorInit]; | |
return self; | |
} | |
- (instancetype)initWithCoder:(NSCoder *)aDecoder | |
{ | |
self = [super initWithCoder:aDecoder]; | |
if (!self) { return nil; } | |
[self commonProgressIndicatorInit]; | |
return self; | |
} | |
- (void)commonProgressIndicatorInit | |
{ | |
// self.layer.borderWidth = 0.5; | |
// self.layer.borderColor = [UIColor whiteColor].CGColor; | |
self.backgroundColor = [UIColor clearColor]; | |
self.ringRadius = CGRectGetWidth(self.frame)/2 | |
- ceil(OEProgressIndicatorRingThickness/2) | |
; | |
self.ringForegroundColor = [[OETheme defaultTheme] colorForKey:@"feed.progressIndicator.tintColor"]; | |
self.ringBackgroundColor = [UIColor colorWithWhite:1 alpha:0.25]; | |
CGPoint center = CGPointMake(CGRectGetWidth(self.bounds)/2, | |
CGRectGetHeight(self.bounds)/2); | |
self.ringLayer = [self createRingLayerWithCenter:center | |
radius:self.ringRadius | |
lineWidth:OEProgressIndicatorRingThickness | |
color:self.ringForegroundColor]; | |
self.ringLayer.anchorPoint = CGPointMake(0.5, 0.5); | |
[self.layer addSublayer:self.ringLayer]; | |
self.backgroundRingLayer = [self createRingLayerWithCenter:center | |
radius:self.ringRadius | |
lineWidth:OEProgressIndicatorRingThickness | |
color:self.ringBackgroundColor]; | |
self.backgroundRingLayer.strokeEnd = 1; | |
[self.layer addSublayer:self.backgroundRingLayer]; | |
[self startAnimating]; | |
} | |
- (void)startAnimating | |
{ | |
if (!self.isAnimating) | |
{ | |
self.animating = YES; | |
self.hidden = NO; | |
[self cancelRingLayerAnimation]; | |
self.ringLayer.strokeEnd = 15.0/360.f; | |
[self runSpinAnimationWithDuration:0.35]; | |
self.alpha = 0; | |
[UIView animateWithDuration:0.65 | |
animations:^{ | |
self.alpha = 1; | |
}]; | |
} | |
} | |
- (void)stopAnimating | |
{ | |
[self cancelRingLayerAnimation]; | |
self.animating = NO; | |
self.hidden = YES; | |
} | |
- (void)showProgress:(CGFloat)progress | |
{ | |
self.hidden = NO; | |
if (self.isAnimating) | |
{ | |
[self stopAnimating]; | |
} | |
if (progress < 0) progress = 0.f; | |
self.ringLayer.strokeEnd = progress; | |
} | |
- (void)runSpinAnimationWithDuration:(CGFloat)duration; | |
{ | |
CABasicAnimation* rotationAnimation; | |
rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"]; | |
rotationAnimation.toValue = [NSNumber numberWithFloat: M_PI * 2.0 /* full rotation*/ * duration]; | |
rotationAnimation.duration = duration; | |
rotationAnimation.cumulative = YES; | |
rotationAnimation.repeatCount = HUGE_VALF; | |
[self.ringLayer addAnimation:rotationAnimation forKey:@"rotationAnimation"]; | |
} | |
// None of these drawRect: approaches work with Xcode 6's IB_DESIGNABLE | |
//- (void)drawRect:(CGRect)rect | |
//{ | |
// CGContextRef currentContext = UIGraphicsGetCurrentContext(); | |
// | |
// // DLog(@"%@ %@", NSStringFromCGRect(self.ringLayer.frame), NSStringFromCGRect(self.backgroundRingLayer.frame) ); | |
// | |
// CGContextTranslateCTM(currentContext, self.ringLayer.frame.origin.x, self.ringLayer.frame.origin.y); | |
// [self.ringLayer renderInContext:currentContext]; | |
// CGContextTranslateCTM(currentContext, -self.ringLayer.frame.origin.x, -self.ringLayer.frame.origin.y); | |
// | |
// CGContextTranslateCTM(currentContext, self.backgroundRingLayer.frame.origin.x, self.backgroundRingLayer.frame.origin.y); | |
// [self.backgroundRingLayer renderInContext:currentContext]; | |
// CGContextTranslateCTM(currentContext, -self.backgroundRingLayer.frame.origin.x, -self.backgroundRingLayer.frame.origin.y); | |
// | |
//// CGRect myFrame = self.bounds; | |
//// CGContextSetLineWidth(currentContext, 10); | |
//// CGRectInset(myFrame, 5, 5); | |
//// [[UIColor greenColor] set]; | |
//// UIRectFrame(myFrame); | |
//} | |
//- (void)drawRect:(CGRect)rect | |
//{ | |
// CGContextRef currentContext = NULL; | |
// UIGraphicsBeginImageContext(self.bounds.size); | |
// currentContext = UIGraphicsGetCurrentContext(); | |
// CGContextTranslateCTM(currentContext, self.ringLayer.frame.origin.x, self.ringLayer.frame.origin.y); | |
// [self.ringLayer renderInContext:currentContext]; | |
// CGContextTranslateCTM(currentContext, -self.ringLayer.frame.origin.x, -self.ringLayer.frame.origin.y); | |
// CGContextTranslateCTM(currentContext, self.backgroundRingLayer.frame.origin.x, self.backgroundRingLayer.frame.origin.y); | |
// [self.backgroundRingLayer renderInContext:currentContext]; | |
// CGContextTranslateCTM(currentContext, -self.backgroundRingLayer.frame.origin.x, -self.backgroundRingLayer.frame.origin.y); | |
// | |
// UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); | |
// UIGraphicsEndImageContext(); | |
// | |
// // NSString* pathToCreate = [NSTemporaryDirectory() stringByAppendingString:@"test.png"]; | |
// // NSData *imageData = [NSData dataWithData:UIImagePNGRepresentation(image)]; | |
// // [imageData writeToFile:pathToCreate atomically:YES]; | |
// | |
// // currentContext = UIGraphicsGetCurrentContext(); | |
// // CGContextDrawImage(currentContext, self.bounds, image.CGImage); | |
// [image drawInRect:self.bounds]; | |
//} | |
#pragma mark - Ring progress animation | |
- (void)cancelRingLayerAnimation | |
{ | |
[CATransaction begin]; | |
[CATransaction setDisableActions:YES]; | |
[self.ringLayer removeAllAnimations]; | |
_ringLayer.strokeEnd = 0.0f; | |
self.layer.transform = CATransform3DRotate(self.layer.transform, 0, 0, 0, 1.f); | |
[CATransaction commit]; | |
} | |
- (CAShapeLayer *)createRingLayerWithCenter:(CGPoint)center | |
radius:(CGFloat)radius | |
lineWidth:(CGFloat)lineWidth | |
color:(UIColor *)color | |
{ | |
UIBezierPath *smoothedPath = [self createCirclePathWithCenter:center | |
radius:radius | |
sampleCount:72]; | |
CAShapeLayer *slice = [CAShapeLayer layer]; | |
slice.frame = CGRectMake(center.x-radius, | |
center.y-radius, | |
radius*2, radius*2); | |
slice.fillColor = [UIColor clearColor].CGColor; | |
slice.strokeColor = color.CGColor; | |
slice.lineWidth = lineWidth; | |
slice.lineCap = kCALineJoinBevel; | |
slice.lineJoin = kCALineJoinBevel; | |
slice.path = smoothedPath.CGPath; | |
return slice; | |
} | |
- (UIBezierPath *)createCirclePathWithCenter:(CGPoint)center | |
radius:(CGFloat)radius | |
sampleCount:(NSInteger)sampleCount | |
{ | |
UIBezierPath *smoothedPath = [UIBezierPath bezierPath]; | |
CGPoint startPoint = [self pointOnCircleWithCenter:center radius:radius angleInDegrees:-90]; | |
[smoothedPath moveToPoint:startPoint]; | |
CGFloat delta = 360.0f/sampleCount; | |
CGFloat angleInDegrees = -90; | |
for (NSInteger i=1; i<sampleCount; i++) | |
{ | |
angleInDegrees += delta; | |
CGPoint point = [self pointOnCircleWithCenter:center radius:radius angleInDegrees:angleInDegrees]; | |
[smoothedPath addLineToPoint:point]; | |
} | |
[smoothedPath addLineToPoint:startPoint]; | |
return smoothedPath; | |
} | |
- (CGPoint)pointOnCircleWithCenter:(CGPoint)center radius:(double)radius angleInDegrees:(double)angleInDegrees | |
{ | |
float x = (float)(radius * cos(angleInDegrees * M_PI / 180)) + radius; | |
float y = (float)(radius * sin(angleInDegrees * M_PI / 180)) + radius; | |
return CGPointMake(x, y); | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment