5 Commits

4 changed files with 54 additions and 22 deletions
+2 -2
View File
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'KDCircularProgress'
s.version = '1.1'
s.version = '1.3'
s.license = 'MIT'
s.summary = 'A circular progress view with gradients written in Swift'
s.homepage = 'https://github.com/kaandedeoglu/KDCircularProgress'
@@ -11,4 +11,4 @@ Pod::Spec.new do |s|
s.source_files = 'KDCircularProgress/*.swift'
s.requires_arc = true
end
end
+50 -18
View File
@@ -188,6 +188,11 @@ public class KDCircularProgress: UIView {
return KDCircularProgressViewLayer.self
}
public override func layoutSubviews() {
super.layoutSubviews()
radius = (frame.size.width/2.0) * 0.8
}
private func setInitialValues() {
radius = (frame.size.width/2.0) * 0.8 //We always apply a 20% padding, stopping glows from being clipped
backgroundColor = .clearColor()
@@ -223,15 +228,24 @@ public class KDCircularProgress: UIView {
progressLayer.setNeedsDisplay()
}
public func animateFromAngle(fromAngle: Int, toAngle: Int, duration: NSTimeInterval, completion: ((Bool) -> Void)?) {
public func animateFromAngle(fromAngle: Int, toAngle: Int, duration: NSTimeInterval, relativeDuration: Bool = true, completion: ((Bool) -> Void)?) {
if isAnimating() {
pauseAnimation()
}
let animationDuration: NSTimeInterval
if relativeDuration {
animationDuration = duration
} else {
let traveledAngle = UtilityFunctions.Mod(toAngle - fromAngle, range: 360, minMax: (0, 360))
let scaledDuration = (NSTimeInterval(traveledAngle) * duration) / 360
animationDuration = scaledDuration
}
let animation = CABasicAnimation(keyPath: "angle")
animation.fromValue = fromAngle
animation.toValue = toAngle
animation.duration = duration
animation.duration = animationDuration
animation.delegate = self
angle = toAngle
animationCompletionBlock = completion
@@ -239,11 +253,11 @@ public class KDCircularProgress: UIView {
progressLayer.addAnimation(animation, forKey: "angle")
}
public func animateToAngle(toAngle: Int, duration: NSTimeInterval, completion: ((Bool) -> Void)?) {
public func animateToAngle(toAngle: Int, duration: NSTimeInterval, relativeDuration: Bool = true, completion: ((Bool) -> Void)?) {
if isAnimating() {
pauseAnimation()
}
animateFromAngle(angle, toAngle: toAngle, duration: duration, completion: completion)
animateFromAngle(angle, toAngle: toAngle, duration: duration, relativeDuration: relativeDuration, completion: completion)
}
public func pauseAnimation() {
@@ -291,11 +305,25 @@ public class KDCircularProgress: UIView {
private class KDCircularProgressViewLayer: CALayer {
@NSManaged var angle: Int
var radius: CGFloat!
var radius: CGFloat! {
didSet {
invalidateGradientCache()
}
}
var startAngle: Int!
var clockwise: Bool!
var clockwise: Bool! {
didSet {
if clockwise != oldValue {
invalidateGradientCache()
}
}
}
var roundedCorners: Bool!
var gradientRotateSpeed: CGFloat!
var gradientRotateSpeed: CGFloat! {
didSet {
invalidateGradientCache()
}
}
var glowAmount: CGFloat!
var glowMode: KDCircularProgressGlowMode!
var progressThickness: CGFloat!
@@ -304,15 +332,14 @@ public class KDCircularProgress: UIView {
var progressInsideFillColor: UIColor = UIColor.clearColor()
var colorsArray: [UIColor]! {
didSet {
gradientCache = nil
locationsCache = nil
invalidateGradientCache()
}
}
var gradientCache: CGGradientRef?
var locationsCache: [CGFloat]?
private var gradientCache: CGGradientRef?
private var locationsCache: [CGFloat]?
struct GlowConstants {
static let sizeToGlowRatio: CGFloat = 0.00015
private struct GlowConstants {
private static let sizeToGlowRatio: CGFloat = 0.00015
static func glowAmountForAngle(angle: Int, glowAmount: CGFloat, glowMode: KDCircularProgressGlowMode, size: CGFloat) -> CGFloat {
switch glowMode {
case .Forward:
@@ -421,12 +448,12 @@ public class KDCircularProgress: UIView {
UIGraphicsPopContext()
}
func fillRectWithContext(ctx: CGContext!, color: UIColor) {
private func fillRectWithContext(ctx: CGContext!, color: UIColor) {
CGContextSetFillColorWithColor(ctx, color.CGColor)
CGContextFillRect(ctx, bounds)
}
func drawGradientWithContext(ctx: CGContext!, componentsArray: [CGFloat]) {
private func drawGradientWithContext(ctx: CGContext!, componentsArray: [CGFloat]) {
let baseSpace = CGColorSpaceCreateDeviceRGB()
let locations = locationsCache ?? gradientLocationsFromColorCount(componentsArray.count/4, gradientWidth: bounds.size.width)
let gradient: CGGradient
@@ -434,9 +461,9 @@ public class KDCircularProgress: UIView {
if let g = self.gradientCache {
gradient = g
} else {
let g = CGGradientCreateWithColorComponents(baseSpace, componentsArray, locations,componentsArray.count / 4)
guard let g = CGGradientCreateWithColorComponents(baseSpace, componentsArray, locations,componentsArray.count / 4) else { return }
self.gradientCache = g
gradient = g!
gradient = g
}
let halfX = bounds.size.width/2.0
@@ -451,7 +478,7 @@ public class KDCircularProgress: UIView {
CGContextDrawLinearGradient(ctx, gradient, startPoint, endPoint, .DrawsBeforeStartLocation)
}
func gradientLocationsFromColorCount(colorCount: Int, gradientWidth: CGFloat) -> [CGFloat] {
private func gradientLocationsFromColorCount(colorCount: Int, gradientWidth: CGFloat) -> [CGFloat] {
if colorCount == 0 || gradientWidth == 0 {
return []
} else {
@@ -469,5 +496,10 @@ public class KDCircularProgress: UIView {
return result
}
}
private func invalidateGradientCache() {
gradientCache = nil
locationsCache = nil
}
}
}
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="8191" systemVersion="15A279b" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" initialViewController="vXZ-lx-hvc">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="8191" systemVersion="15A284" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" initialViewController="vXZ-lx-hvc">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="8154"/>
@@ -35,7 +35,7 @@ class ViewController: UIViewController {
}
@IBAction func animateButtonTapped(sender: UIButton) {
progress.animateToAngle(360, duration: 5) { completed in
progress.animateFromAngle(0, toAngle: 360, duration: 5) { completed in
if completed {
print("animation stopped, completed")
} else {