Skip to content

Commit d1809ee

Browse files
committed
new progress bar
1 parent 360806f commit d1809ee

9 files changed

+343
-70
lines changed

SwiftyProgressBar.xcodeproj/project.pbxproj

+14
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
96139EB61D0B501B00F4625F /* SwiftyProgressBarTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96139EB51D0B501B00F4625F /* SwiftyProgressBarTests.swift */; };
1717
96139EC11D0B506C00F4625F /* CircleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96139EC01D0B506C00F4625F /* CircleView.swift */; };
1818
963B67201D48871200C53D2C /* ReverseCircularProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 963B671F1D48871200C53D2C /* ReverseCircularProgressView.swift */; };
19+
96E57DF91DFEB9AA00CA22DE /* CircularProgressBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96E57DF81DFEB9AA00CA22DE /* CircularProgressBar.swift */; };
20+
96E57DFB1DFEBD2500CA22DE /* BaseCircleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96E57DFA1DFEBD2500CA22DE /* BaseCircleView.swift */; };
1921
/* End PBXBuildFile section */
2022

2123
/* Begin PBXContainerItemProxy section */
@@ -39,6 +41,8 @@
3941
96139EB71D0B501B00F4625F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
4042
96139EC01D0B506C00F4625F /* CircleView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CircleView.swift; sourceTree = "<group>"; };
4143
963B671F1D48871200C53D2C /* ReverseCircularProgressView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReverseCircularProgressView.swift; sourceTree = "<group>"; };
44+
96E57DF81DFEB9AA00CA22DE /* CircularProgressBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CircularProgressBar.swift; sourceTree = "<group>"; };
45+
96E57DFA1DFEBD2500CA22DE /* BaseCircleView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseCircleView.swift; sourceTree = "<group>"; };
4246
/* End PBXFileReference section */
4347

4448
/* Begin PBXFrameworksBuildPhase section */
@@ -85,7 +89,9 @@
8589
96139EA91D0B501B00F4625F /* TorProgressBar.h */,
8690
96139EAB1D0B501B00F4625F /* Info.plist */,
8791
96139EC01D0B506C00F4625F /* CircleView.swift */,
92+
96E57DFA1DFEBD2500CA22DE /* BaseCircleView.swift */,
8893
960B4B661D0C522A0066B58C /* CircularProgressView.swift */,
94+
96E57DF81DFEB9AA00CA22DE /* CircularProgressBar.swift */,
8995
963B671F1D48871200C53D2C /* ReverseCircularProgressView.swift */,
9096
);
9197
path = SwiftyProgressBar;
@@ -165,9 +171,11 @@
165171
96139EA51D0B501B00F4625F = {
166172
CreatedOnToolsVersion = 7.2;
167173
DevelopmentTeam = B92W98DN9L;
174+
LastSwiftMigration = 0810;
168175
};
169176
96139EAF1D0B501B00F4625F = {
170177
CreatedOnToolsVersion = 7.2;
178+
LastSwiftMigration = 0810;
171179
};
172180
};
173181
};
@@ -214,7 +222,9 @@
214222
96139EC11D0B506C00F4625F /* CircleView.swift in Sources */,
215223
960B4B671D0C522A0066B58C /* CircularProgressView.swift in Sources */,
216224
960B4B6D1D0C6BB20066B58C /* Test.swift in Sources */,
225+
96E57DFB1DFEBD2500CA22DE /* BaseCircleView.swift in Sources */,
217226
963B67201D48871200C53D2C /* ReverseCircularProgressView.swift in Sources */,
227+
96E57DF91DFEB9AA00CA22DE /* CircularProgressBar.swift in Sources */,
218228
);
219229
runOnlyForDeploymentPostprocessing = 0;
220230
};
@@ -346,6 +356,7 @@
346356
PROVISIONING_PROFILE = "";
347357
SKIP_INSTALL = YES;
348358
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
359+
SWIFT_VERSION = 3.0;
349360
};
350361
name = Debug;
351362
};
@@ -366,6 +377,7 @@
366377
PRODUCT_NAME = SwiftyProgressBar;
367378
PROVISIONING_PROFILE = "";
368379
SKIP_INSTALL = YES;
380+
SWIFT_VERSION = 3.0;
369381
};
370382
name = Release;
371383
};
@@ -376,6 +388,7 @@
376388
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
377389
PRODUCT_BUNDLE_IDENTIFIER = com.torishere.SwiftyProgressBarTests;
378390
PRODUCT_NAME = SwiftyProgressBar;
391+
SWIFT_VERSION = 3.0;
379392
};
380393
name = Debug;
381394
};
@@ -386,6 +399,7 @@
386399
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
387400
PRODUCT_BUNDLE_IDENTIFIER = com.torishere.SwiftyProgressBarTests;
388401
PRODUCT_NAME = SwiftyProgressBar;
402+
SWIFT_VERSION = 3.0;
389403
};
390404
name = Release;
391405
};

SwiftyProgressBar.xcodeproj/xcshareddata/xcschemes/SwiftyProgressBar.xcscheme

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<Scheme
3-
LastUpgradeVersion = "0730"
3+
LastUpgradeVersion = "0820"
44
version = "1.3">
55
<BuildAction
66
parallelizeBuildables = "YES"
+193
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
//
2+
// BaseCircleView.swift
3+
// SwiftyProgressBar
4+
//
5+
// Created by Kittikorn Ariyasuk on 2016/12/12.
6+
// Copyright © 2016 TorIsHere. All rights reserved.
7+
//
8+
9+
import UIKit
10+
11+
let π:CGFloat = CGFloat(M_PI)
12+
13+
extension CGFloat {
14+
var doubleValue: Double { return Double(self) }
15+
var degreesToRadians: CGFloat { return CGFloat(doubleValue * M_PI / 180) }
16+
var radiansToDegrees: CGFloat { return CGFloat(doubleValue * 180 / M_PI) }
17+
}
18+
19+
@IBDesignable open class BaseCircleView: UIView {
20+
let queue = DispatchQueue(label: "com.torishere.progress-queue")
21+
22+
public enum CircleSize:CGFloat {
23+
case Big = 30
24+
case Medium = 15
25+
case Small = 8
26+
}
27+
28+
@IBInspectable open var circleSize:CircleSize = .Medium
29+
@IBInspectable open var fgColor: UIColor = UIColor.blue
30+
@IBInspectable open var bgColor: UIColor = UIColor.gray
31+
@IBInspectable open var lineWidth:CGFloat = 6
32+
@IBInspectable open var bgLineWidth:CGFloat = 5
33+
@IBInspectable open var startAngle:CGFloat = -90
34+
@IBInspectable open var endAngle:CGFloat = -90
35+
@IBInspectable open var willDraw:Bool = true
36+
37+
38+
/*
39+
// Only override draw() if you perform custom drawing.
40+
// An empty implementation adversely affects performance during animation.
41+
override func draw(_ rect: CGRect) {
42+
// Drawing code
43+
}
44+
*/
45+
46+
open func drawProgressBar(frame: CGRect = CGRect(x: 0, y: 0, width: 100, height: 100), progress: CGFloat = 100, fgColor: UIColor = UIColor.blue, bgColor: UIColor = UIColor.gray) {
47+
48+
let center = CGPoint(x:self.bounds.width/2, y: bounds.height/2)
49+
let radius: CGFloat = max(self.bounds.width, bounds.height)
50+
51+
52+
let bgPath:UIBezierPath = UIBezierPath(arcCenter: center,
53+
radius: radius/2 - lineWidth/2,
54+
startAngle: -90,
55+
endAngle: 90,
56+
clockwise: true)
57+
bgPath.lineWidth = self.bgLineWidth
58+
bgColor.setStroke()
59+
bgPath.stroke()
60+
61+
62+
self.endAngle = self.startAngle + (progress * 360)
63+
let progressPath:UIBezierPath = self.generatePath(startAngle: self.startAngle, endAngle: self.endAngle, size: self.circleSize)
64+
fgColor.setStroke()
65+
progressPath.stroke()
66+
}
67+
68+
open func drawProgressBarWithAnimate(frame: CGRect = CGRect(x: 0, y: 0, width: 100, height: 100), progress: CGFloat = 100, fgColor: UIColor = UIColor.blue, bgColor: UIColor = UIColor.gray, callback: (() -> Void)?) {
69+
70+
let center = CGPoint(x:self.bounds.width/2, y: bounds.height/2)
71+
let radius: CGFloat = max(self.bounds.width, bounds.height)
72+
73+
74+
let bgPath:UIBezierPath = UIBezierPath(arcCenter: center,
75+
radius: radius/2 - lineWidth/2,
76+
startAngle: -90,
77+
endAngle: 90,
78+
clockwise: true)
79+
bgPath.lineWidth = self.bgLineWidth
80+
bgColor.setStroke()
81+
bgPath.stroke()
82+
83+
self.endAngle = self.startAngle + (progress * 360)
84+
let progressPath:UIBezierPath = self.generatePath(startAngle: self.startAngle, endAngle: self.endAngle, size: self.circleSize)
85+
fgColor.setStroke()
86+
87+
let progressLayer = CAShapeLayer()
88+
progressLayer.path = progressPath.cgPath
89+
progressLayer.lineCap = kCALineCapRound
90+
progressLayer.lineWidth = self.lineWidth
91+
progressLayer.lineJoin = kCALineJoinBevel
92+
progressLayer.strokeColor = self.fgColor.cgColor
93+
progressLayer.fillColor = UIColor.clear.cgColor
94+
self.layer.addSublayer(progressLayer)
95+
96+
97+
CATransaction.begin()
98+
99+
CATransaction.setCompletionBlock({
100+
if let callback = callback {
101+
callback()
102+
}
103+
})
104+
105+
self.progressAnimate(shapeLayer: progressLayer, progress: progress)
106+
CATransaction.commit()
107+
108+
}
109+
110+
open func hideView() {
111+
self.isHidden = true
112+
}
113+
114+
private func progressAnimate(shapeLayer: CAShapeLayer, progress:CGFloat) {
115+
let animProgress = CABasicAnimation(keyPath: "strokeEnd")
116+
animProgress.fromValue = 0.0
117+
animProgress.toValue = 1.0
118+
animProgress.duration = Double(progress) / 1.0
119+
animProgress.repeatCount = 0
120+
shapeLayer.add(animProgress, forKey: "strokeEnd")
121+
}
122+
123+
private func generatePath(startAngle:CGFloat, endAngle:CGFloat, size:CircleSize) -> UIBezierPath {
124+
let center = CGPoint(x:self.bounds.width/2, y: bounds.height/2)
125+
let radius: CGFloat = max(self.bounds.width, bounds.height)
126+
127+
let path = UIBezierPath(arcCenter: center,
128+
radius: radius/2 - lineWidth/2,
129+
startAngle: startAngle.degreesToRadians,
130+
endAngle: endAngle.degreesToRadians,
131+
clockwise: true)
132+
133+
switch size {
134+
case .Big:
135+
path.lineWidth = CircleSize.Big.rawValue
136+
case .Medium:
137+
path.lineWidth = CircleSize.Medium.rawValue
138+
case .Small:
139+
path.lineWidth = CircleSize.Small.rawValue
140+
default:
141+
path.lineWidth = CircleSize.Medium.rawValue
142+
}
143+
144+
path.lineCapStyle = CGLineCap.round
145+
146+
return path
147+
}
148+
149+
override public init (frame : CGRect) {
150+
super.init(frame : frame)
151+
}
152+
153+
convenience public init () {
154+
self.init(frame:CGRect.zero)
155+
}
156+
157+
required public init?(coder aDecoder: NSCoder) {
158+
//fatalError("init(coder:) has not been implemented")
159+
super.init(coder: aDecoder)
160+
}
161+
162+
}
163+
164+
struct Future<T> {
165+
typealias FutureResultHandler = (T) -> ()
166+
typealias AsyncOperation = (@escaping FutureResultHandler) -> ()
167+
168+
private let asyncOperation: AsyncOperation
169+
170+
init(asyncOperation: @escaping AsyncOperation) {
171+
self.asyncOperation = asyncOperation
172+
}
173+
174+
func resolve(_ handler: @escaping FutureResultHandler) {
175+
asyncOperation(handler)
176+
}
177+
178+
func then<U>(_ next: @escaping (_ input: T, _ callback: @escaping (U) -> ()) -> ()) -> Future<U> {
179+
return Future<U> { (resultHandler) in
180+
self.resolve { firstResult in
181+
next(firstResult) { secondResult in
182+
resultHandler(secondResult)
183+
}
184+
}
185+
}
186+
}
187+
}
188+
189+
190+
191+
192+
193+

SwiftyProgressBar/CircleView.swift

+13-21
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,16 @@
88

99
import UIKit
1010

11-
let π:CGFloat = CGFloat(M_PI)
11+
@IBDesignable open class CircleView: UIView {
1212

13-
extension CGFloat {
14-
var doubleValue: Double { return Double(self) }
15-
var degreesToRadians: CGFloat { return CGFloat(doubleValue * M_PI / 180) }
16-
var radiansToDegrees: CGFloat { return CGFloat(doubleValue * 180 / M_PI) }
17-
}
18-
19-
@IBDesignable public class CircleView: UIView {
20-
21-
@IBInspectable public var primaryColor: UIColor = UIColor.blueColor()
22-
@IBInspectable public var secondaryColor: UIColor = UIColor.grayColor()
23-
@IBInspectable public var bgColor: UIColor = UIColor.grayColor()
24-
@IBInspectable public var lineWidth:CGFloat = 6
25-
@IBInspectable public var bgLineWidth:CGFloat = 6
26-
@IBInspectable public var startAngle:CGFloat = -90
27-
@IBInspectable public var endAngle:CGFloat = -90
28-
@IBInspectable public var willDraw:Bool = true
13+
@IBInspectable open var primaryColor: UIColor = UIColor.blue
14+
@IBInspectable open var secondaryColor: UIColor = UIColor.gray
15+
@IBInspectable open var bgColor: UIColor = UIColor.gray
16+
@IBInspectable open var lineWidth:CGFloat = 6
17+
@IBInspectable open var bgLineWidth:CGFloat = 6
18+
@IBInspectable open var startAngle:CGFloat = -90
19+
@IBInspectable open var endAngle:CGFloat = -90
20+
@IBInspectable open var willDraw:Bool = true
2921

3022
var gradientLayer:CAGradientLayer!
3123
var pathLayer:CAShapeLayer!
@@ -34,9 +26,9 @@ extension CGFloat {
3426

3527
// Only override drawRect: if you perform custom drawing.
3628
// An empty implementation adversely affects performance during animation.
37-
override public func drawRect(rect: CGRect) {
29+
override open func draw(_ rect: CGRect) {
3830
// Drawing code
39-
super.drawRect(rect)
31+
super.draw(rect)
4032

4133
let center = CGPoint(x:bounds.width/2, y: bounds.height/2)
4234
let radius: CGFloat = max(bounds.width, bounds.height)
@@ -48,7 +40,7 @@ extension CGFloat {
4840
clockwise: true)
4941

5042
path.lineWidth = lineWidth
51-
path.lineCapStyle = CGLineCap.Round
43+
path.lineCapStyle = CGLineCap.round
5244

5345
bgPath = UIBezierPath(arcCenter: center,
5446
radius: radius/2 - lineWidth/2,
@@ -79,4 +71,4 @@ extension CGFloat {
7971
super.init(coder: aDecoder)
8072
}
8173

82-
}
74+
}

0 commit comments

Comments
 (0)