-
Notifications
You must be signed in to change notification settings - Fork 0
/
RadialProgressView.swift
100 lines (76 loc) · 3.58 KB
/
RadialProgressView.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
// Dominic Holmes - 7/19/2017
import UIKit
class RadialProgressView: UIView {
let progressCircleLayer: CAShapeLayer!
let staticCircleLayer: CAShapeLayer!
// Progress circle is drawn on top of lighter colored static circle
var progressStroke: UIColor = .black
var progressFill: UIColor = .clear
var staticStroke: UIColor = .lightGray
var staticFill: UIColor = .clear
// Circle line thickness
var lineWidth: CGFloat = 1.0
// Between 0 and 1, denotes how much of circle is filled
var progress: CGFloat = 0.0
override init(frame: CGRect) {
staticCircleLayer = CAShapeLayer()
progressCircleLayer = CAShapeLayer()
super.init(frame: frame)
createCircles()
}
required init?(coder aDecoder: NSCoder) {
staticCircleLayer = CAShapeLayer()
progressCircleLayer = CAShapeLayer()
super.init(coder: aDecoder)
createCircles()
}
func createCircles() {
// Create path (includes entire circle)
// Careful messing with start/end angle and clockwise
let circlePath = UIBezierPath(
arcCenter: CGPoint(
x: frame.size.width / 2.0,
y: frame.size.height / 2.0),
radius: (frame.size.width - 10)/2,
startAngle: CGFloat(Double.pi * -0.5),
endAngle: CGFloat(Double.pi * -2.5),
clockwise: false)
// Set up staticCircleLayer with the path, color, and line width
staticCircleLayer.path = circlePath.cgPath
staticCircleLayer.fillColor = staticFill.cgColor
staticCircleLayer.strokeColor = staticStroke.cgColor
staticCircleLayer.lineWidth = lineWidth
// Set up progressCircleLayer with the path, color, and line width
progressCircleLayer.path = circlePath.cgPath
progressCircleLayer.fillColor = progressFill.cgColor
progressCircleLayer.strokeColor = progressStroke.cgColor
progressCircleLayer.lineWidth = lineWidth
// Initially draw the static portion of the circle
staticCircleLayer.strokeEnd = 1.0
// Initially draw current progress
progressCircleLayer.strokeEnd = progress
// Add progressCircleLayer and staticCircleLayer to the view's CoreAnimations layer
layer.addSublayer(staticCircleLayer)
layer.addSublayer(progressCircleLayer)
}
func setValueAnimated(
duration: TimeInterval,
newProgressValue: CGFloat) {
// Animate the strokeEnd property of the progressCircleLayer
let animation = CABasicAnimation(keyPath: "strokeEnd")
animation.duration = duration
// From start value to end value (0 to 1)
animation.fromValue = progress
animation.toValue = newProgressValue
// Uncomment your preferred animation style ->
//animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
//animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn)
//animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
// Ensures strokeEnd property is the right value when animation ends
progressCircleLayer.strokeEnd = newProgressValue
self.progress = newProgressValue
// Add the animation
progressCircleLayer.add(animation, forKey: "animateCircle")
}
}