Skip to content

Instantly share code, notes, and snippets.

@rsanchezsaez
Created October 8, 2014 09:45
Show Gist options
  • Save rsanchezsaez/ac620ce58bd6097207d8 to your computer and use it in GitHub Desktop.
Save rsanchezsaez/ac620ce58bd6097207d8 to your computer and use it in GitHub Desktop.
//
// 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
//
// 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