DACircularProgress是一个第三方的progressView.
绘制
绘制的工作主要在circularProgressLayer
里完成.
- (void)drawInContext:(CGContextRef)context
1 2 3 4 5 6 7
| CGMutablePathRef trackPath = CGPathCreateMutable(); CGPathMoveToPoint(trackPath, NULL, centerPoint.x, centerPoint.y); CGPathAddArc(trackPath, NULL, centerPoint.x, centerPoint.y, radius, (float)(2.0f * M_PI), 0.0f, TRUE); CGPathCloseSubpath(trackPath); CGContextAddPath(context, trackPath); CGContextFillPath(context); CGPathRelease(trackPath);
|
绘制背景圆
1 2 3 4 5 6 7 8 9 10
| if (progress > 0.0f) { CGContextSetFillColorWithColor(context, self.progressTintColor.CGColor); CGMutablePathRef progressPath = CGPathCreateMutable(); CGPathMoveToPoint(progressPath, NULL, centerPoint.x, centerPoint.y); CGPathAddArc(progressPath, NULL, centerPoint.x, centerPoint.y, radius, (float)(3.0f * M_PI_2), radians, !clockwise); CGPathCloseSubpath(progressPath); CGContextAddPath(context, progressPath); CGContextFillPath(context); CGPathRelease(progressPath); }
|
绘制进度部分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| if (progress > 0.0f && self.roundedCorners) { CGFloat pathWidth = radius * self.thicknessRatio; CGFloat xOffset = radius * (1.0f + ((1.0f - (self.thicknessRatio / 2.0f)) * cosf(radians))); CGFloat yOffset = radius * (1.0f + ((1.0f - (self.thicknessRatio / 2.0f)) * sinf(radians))); CGPoint endPoint = CGPointMake(xOffset, yOffset); CGRect startEllipseRect = (CGRect) { .origin.x = centerPoint.x - pathWidth / 2.0f, .origin.y = 0.0f, .size.width = pathWidth, .size.height = pathWidth }; CGContextAddEllipseInRect(context, startEllipseRect); CGContextFillPath(context); CGRect endEllipseRect = (CGRect) { .origin.x = endPoint.x - pathWidth / 2.0f, .origin.y = endPoint.y - pathWidth / 2.0f, .size.width = pathWidth, .size.height = pathWidth }; CGContextAddEllipseInRect(context, endEllipseRect); CGContextFillPath(context); }
|
绘制圆角,具体是绘制一个圆,一般和进度部分重合,这部分看不到,另一部分就有了圆角效果.
1 2 3 4 5 6 7 8 9 10
| CGContextSetBlendMode(context, kCGBlendModeClear); CGFloat innerRadius = radius * (1.0f - self.thicknessRatio); CGRect clearRect = (CGRect) { .origin.x = centerPoint.x - innerRadius, .origin.y = centerPoint.y - innerRadius, .size.width = innerRadius * 2.0f, .size.height = innerRadius * 2.0f }; CGContextAddEllipseInRect(context, clearRect); CGContextFillPath(context);
|
清除中间部分
如果没去除去除中间部分,并且吧圆角部分改成红色,就会变成这个样子.
##疑问
在- (void)drawInContext:(CGContextRef)context
里输出progress
的值
1
| NSLog(@"%f",self.progress);
|
输出如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| 2016-04-20 22:48:38.968 DACTest[2836:557670] 0.000000 2016-04-20 22:48:38.986 DACTest[2836:557670] 0.025026 2016-04-20 22:48:39.007 DACTest[2836:557670] 0.054017 2016-04-20 22:48:39.025 DACTest[2836:557670] 0.085763 2016-04-20 22:48:39.043 DACTest[2836:557670] 0.125796 2016-04-20 22:48:39.060 DACTest[2836:557670] 0.170546 2016-04-20 22:48:39.080 DACTest[2836:557670] 0.224875 2016-04-20 22:48:39.098 DACTest[2836:557670] 0.275629 2016-04-20 22:48:39.121 DACTest[2836:557670] 0.339246 2016-04-20 22:48:39.139 DACTest[2836:557670] 0.384856 2016-04-20 22:48:39.157 DACTest[2836:557670] 0.423214 2016-04-20 22:48:39.175 DACTest[2836:557670] 0.453805 2016-04-20 22:48:39.193 DACTest[2836:557670] 0.476371 2016-04-20 22:48:39.234 DACTest[2836:557670] 0.499733 2016-04-20 22:48:39.252 DACTest[2836:557670] 0.500000
|
这是layer的presentationLayer
的progess
的值,并不是moduleLayer
的progress
的值,与objccn说的不一样.
-setProgress:animated:
通过调用DACircularProgressView
的-setProgress:animated:
改变进度.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| CGFloat pinnedProgress = MIN(MAX(progress, 0.0f), 1.0f); if (animated) { CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"progress"]; animation.duration = duration; animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; animation.fillMode = kCAFillModeForwards; animation.fromValue = [NSNumber numberWithFloat:self.progress]; animation.toValue = [NSNumber numberWithFloat:pinnedProgress]; animation.beginTime = CACurrentMediaTime() + initialDelay; animation.delegate = self; [self.circularProgressLayer addAnimation:animation forKey:@"progress"]; } else { [self.circularProgressLayer setNeedsDisplay]; self.circularProgressLayer.progress = pinnedProgress; }
|
这段创建了一个CABasicAnimation
对象,CABasicAnimation
会为fromValue
和toValue
之间自动插值.
因为DACircularProgressLayer
实现了-needsDisplayForKey:
方法,所以当CABasicAnimation
将progress
的值从fromValue
到toValue
之间自动变化时,会自动调用-needsDisplayForKey:
方法
1 2 3 4 5 6 7 8
| + (BOOL)needsDisplayForKey:(NSString *)key { if ([key isEqualToString:@"progress"]) { return YES; } else { return [super needsDisplayForKey:key]; } }
|
当-needsDisplayForKey:
返回true
时,-drawInContext:
会被调用,上述的绘制过程将被执行.