Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| eeacb59a55 | |||
| ee5890b8ce | |||
| d116d7c380 | |||
| 2ec2d6f783 | |||
| 02dccb0804 | |||
| 74c2c3c8d7 | |||
| f9194ec712 | |||
| 54e24f1053 | |||
| 2385466f70 | |||
| ab6a4fd165 | |||
| 5fe36abfe2 |
@@ -1,6 +1,6 @@
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'KDCircularProgress'
|
||||
s.version = '1.1'
|
||||
s.version = '1.3.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
|
||||
|
||||
@@ -171,23 +171,28 @@ public class KDCircularProgress: UIView {
|
||||
self.init(frame: frame)
|
||||
setColors(colors)
|
||||
}
|
||||
|
||||
|
||||
required public init(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)!
|
||||
translatesAutoresizingMaskIntoConstraints = false
|
||||
userInteractionEnabled = false
|
||||
setInitialValues()
|
||||
super.init(coder: aDecoder)!
|
||||
translatesAutoresizingMaskIntoConstraints = false
|
||||
userInteractionEnabled = false
|
||||
setInitialValues()
|
||||
refreshValues()
|
||||
}
|
||||
}
|
||||
|
||||
public override func awakeFromNib() {
|
||||
checkAndSetIBColors()
|
||||
}
|
||||
|
||||
|
||||
override public class func layerClass() -> AnyClass {
|
||||
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,15 +253,15 @@ 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() {
|
||||
let presentationLayer = progressLayer.presentationLayer() as! KDCircularProgressViewLayer
|
||||
guard let presentationLayer = progressLayer.presentationLayer() as? KDCircularProgressViewLayer else { return }
|
||||
let currentValue = presentationLayer.angle
|
||||
progressLayer.removeAllAnimations()
|
||||
animationCompletionBlock = nil
|
||||
@@ -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:
|
||||
@@ -346,12 +373,13 @@ public class KDCircularProgress: UIView {
|
||||
trackThickness = progressLayer.trackThickness
|
||||
trackColor = progressLayer.trackColor
|
||||
colorsArray = progressLayer.colorsArray
|
||||
progressInsideFillColor = progressLayer.progressInsideFillColor
|
||||
}
|
||||
|
||||
|
||||
override init() {
|
||||
super.init()
|
||||
}
|
||||
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)
|
||||
}
|
||||
@@ -371,7 +399,7 @@ public class KDCircularProgress: UIView {
|
||||
CGContextSetLineWidth(ctx, trackLineWidth)
|
||||
CGContextSetLineCap(ctx, CGLineCap.Butt)
|
||||
CGContextDrawPath(ctx, .FillStroke)
|
||||
|
||||
|
||||
UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
|
||||
let imageCtx = UIGraphicsGetCurrentContext()
|
||||
let reducedAngle = UtilityFunctions.Mod(angle, range: 360, minMax: (0, 360))
|
||||
@@ -421,22 +449,22 @@ 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
|
||||
|
||||
|
||||
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 +479,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 +497,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 {
|
||||
|
||||
@@ -8,8 +8,9 @@ Here's an example
|
||||
[Youtube Link](http://youtu.be/iIdas72MXOg)
|
||||
|
||||
|
||||
[](http://youtu.be/iIdas72MXOg)
|
||||

|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
@@ -100,11 +101,13 @@ public func setColors(colors: UIColor...)
|
||||
Set the colors for the progress gradient.
|
||||
|
||||
```swift
|
||||
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)?)
|
||||
```
|
||||
|
||||
Animate the progress from an initial value to a final value, with a completion block that fires after the animation is done.
|
||||
|
||||
`relativeDuration` - specify if the duration is for the specific animation or is the duration that would make a full turn.
|
||||
|
||||
```swift
|
||||
public func animateToAngle(toAngle: Int, duration: NSTimeInterval, completion: ((Bool) -> Void)?)
|
||||
```
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 861 KiB |
Reference in New Issue
Block a user