// // JGProgressHUDRingIndicatorView.m // JGProgressHUD // // Created by Jonas Gessner on 20.7.14. // Copyright (c) 2014 Jonas Gessner. All rights reserved. // #import "JGProgressHUDRingIndicatorView.h" @interface JGProgressHUDRingIndicatorLayer : CALayer @property (nonatomic, assign) float progress; @property (nonatomic, weak) UIColor *ringColor; @property (nonatomic, weak) UIColor *ringBackgroundColor; @property (nonatomic, assign) BOOL roundProgressLine; @property (nonatomic, assign) CGFloat ringWidth; @end @implementation JGProgressHUDRingIndicatorLayer @dynamic progress, ringBackgroundColor, ringColor, ringWidth, roundProgressLine; + (BOOL)needsDisplayForKey:(NSString *)key { return ([key isEqualToString:@"progress"] || [key isEqualToString:@"ringColor"] || [key isEqualToString:@"ringBackgroundColor"] || [key isEqualToString:@"roundProgressLine"] || [key isEqualToString:@"ringWidth"] || [super needsDisplayForKey:key]); } - (id )actionForKey:(NSString *)key { if ([key isEqualToString:@"progress"]) { CABasicAnimation *progressAnimation = [CABasicAnimation animation]; progressAnimation.fromValue = [self.presentationLayer valueForKey:key]; progressAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; return progressAnimation; } return [super actionForKey:key]; } - (void)drawInContext:(CGContextRef)ctx { UIGraphicsPushContext(ctx); CGRect rect = self.bounds; CGPoint center = CGPointMake(rect.origin.x + (CGFloat)floor(rect.size.width/2.0), rect.origin.y + (CGFloat)floor(rect.size.height/2.0)); CGFloat lineWidth = self.ringWidth; CGFloat radius = (CGFloat)floor(MIN(rect.size.width, rect.size.height)/2.0) - lineWidth; //Background [self.ringBackgroundColor setStroke]; UIBezierPath *borderPath = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:0.0 endAngle:2.0*(CGFloat)M_PI clockwise:NO]; [borderPath setLineWidth:lineWidth]; [borderPath stroke]; //Progress [self.ringColor setStroke]; if (self.progress > 0.0) { UIBezierPath *processPath = [UIBezierPath bezierPath]; [processPath setLineWidth:lineWidth]; [processPath setLineCapStyle:(self.roundProgressLine ? kCGLineCapRound : kCGLineCapSquare)]; CGFloat startAngle = -((CGFloat)M_PI / 2.0); CGFloat endAngle = startAngle + 2.0 * (CGFloat)M_PI * self.progress; [processPath addArcWithCenter:center radius:radius startAngle:startAngle endAngle:endAngle clockwise:YES]; [processPath stroke]; } UIGraphicsPopContext(); } @end @implementation JGProgressHUDRingIndicatorView #pragma mark - Initializers - (instancetype)init { self = [super initWithContentView:nil];; if (self) { self.layer.contentsScale = [UIScreen mainScreen].scale; [self.layer setNeedsDisplay]; self.ringWidth = 3.0; self.ringColor = [UIColor clearColor]; self.ringBackgroundColor = [UIColor clearColor]; } return self; } - (instancetype)initWithHUDStyle:(JGProgressHUDStyle)style { return [self init]; } - (instancetype)initWithContentView:(UIView *)contentView { return [self init]; } #pragma mark - Getters & Setters - (void)setRoundProgressLine:(BOOL)roundProgressLine { if (roundProgressLine == self.roundProgressLine) { return; } _roundProgressLine = roundProgressLine; [(JGProgressHUDRingIndicatorLayer *)self.layer setRoundProgressLine:self.roundProgressLine]; } - (void)setRingColor:(UIColor *)tintColor { if ([tintColor isEqual:self.ringColor]) { return; } _ringColor = tintColor; [(JGProgressHUDRingIndicatorLayer *)self.layer setRingColor:self.ringColor]; } - (void)setRingBackgroundColor:(UIColor *)backgroundTintColor { if ([backgroundTintColor isEqual:self.ringBackgroundColor]) { return; } _ringBackgroundColor = backgroundTintColor; [(JGProgressHUDRingIndicatorLayer *)self.layer setRingBackgroundColor:self.ringBackgroundColor]; } - (void)setRingWidth:(CGFloat)ringWidth { if (fequal(ringWidth, self.ringWidth)) { return; } _ringWidth = ringWidth; [(JGProgressHUDRingIndicatorLayer *)self.layer setRingWidth:self.ringWidth]; } - (void)setProgress:(float)progress animated:(BOOL)animated { if (fequal(self.progress, progress)) { return; } [super setProgress:progress animated:animated]; [CATransaction begin]; [CATransaction setAnimationDuration:(animated ? 0.3 : 0.0)]; [(JGProgressHUDRingIndicatorLayer *)self.layer setProgress:self.progress]; [CATransaction commit]; } #pragma mark - Overrides - (void)setUpForHUDStyle:(JGProgressHUDStyle)style vibrancyEnabled:(BOOL)vibrancyEnabled { [super setUpForHUDStyle:style vibrancyEnabled:vibrancyEnabled]; if (style == JGProgressHUDStyleDark) { self.ringColor = [UIColor colorWithWhite:1.0 alpha:1.0]; self.ringBackgroundColor = [UIColor colorWithWhite:0.0 alpha:1.0]; } else { self.ringColor = [UIColor blackColor]; if (style == JGProgressHUDStyleLight) { self.ringBackgroundColor = [UIColor colorWithWhite:0.85 alpha:1.0]; } else { self.ringBackgroundColor = [UIColor colorWithWhite:0.9 alpha:1.0]; } } } + (Class)layerClass { return [JGProgressHUDRingIndicatorLayer class]; } @end