1 Commits

12 changed files with 155 additions and 216 deletions
+1 -1
View File
@@ -1 +1 @@
4.0
3.0
@@ -7,8 +7,6 @@
objects = {
/* Begin PBXBuildFile section */
3CFA1D9A21720FB70094F95E /* KDCircularProgress.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BC6FF0C71D92FEA9002E6571 /* KDCircularProgress.framework */; };
3CFA1D9B21720FB70094F95E /* KDCircularProgress.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = BC6FF0C71D92FEA9002E6571 /* KDCircularProgress.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
BC5B0C1D1D92F75600B43506 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC5B0C1C1D92F75600B43506 /* AppDelegate.swift */; };
BC5B0C1F1D92F75600B43506 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC5B0C1E1D92F75600B43506 /* ViewController.swift */; };
BC5B0C221D92F75600B43506 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BC5B0C201D92F75600B43506 /* Main.storyboard */; };
@@ -17,13 +15,6 @@
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
3CFA1D9C21720FB70094F95E /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = BC5B0C2E1D92F76E00B43506 /* KDCircularProgress.xcodeproj */;
proxyType = 1;
remoteGlobalIDString = BC5B0BE71D92F4FA00B43506;
remoteInfo = "KDCircularProgress iOS";
};
BC6FF0C61D92FEA9002E6571 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = BC5B0C2E1D92F76E00B43506 /* KDCircularProgress.xcodeproj */;
@@ -33,20 +24,6 @@
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
3CFA1D9E21720FB70094F95E /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
3CFA1D9B21720FB70094F95E /* KDCircularProgress.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
BC5B0C191D92F75600B43506 /* iOS Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "iOS Example.app"; sourceTree = BUILT_PRODUCTS_DIR; };
BC5B0C1C1D92F75600B43506 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
@@ -63,7 +40,6 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
3CFA1D9A21720FB70094F95E /* KDCircularProgress.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -118,12 +94,10 @@
BC5B0C151D92F75600B43506 /* Sources */,
BC5B0C161D92F75600B43506 /* Frameworks */,
BC5B0C171D92F75600B43506 /* Resources */,
3CFA1D9E21720FB70094F95E /* Embed Frameworks */,
);
buildRules = (
);
dependencies = (
3CFA1D9D21720FB70094F95E /* PBXTargetDependency */,
);
name = "iOS Example";
productName = "iOS Example";
@@ -137,19 +111,18 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0800;
LastUpgradeCheck = 1000;
LastUpgradeCheck = 0800;
ORGANIZATIONNAME = "Kaan Dedeoglu";
TargetAttributes = {
BC5B0C181D92F75600B43506 = {
CreatedOnToolsVersion = 8.0;
LastSwiftMigration = 1020;
ProvisioningStyle = Automatic;
};
};
};
buildConfigurationList = BC5B0C141D92F75600B43506 /* Build configuration list for PBXProject "iOS Example" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = en;
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
@@ -206,14 +179,6 @@
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
3CFA1D9D21720FB70094F95E /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = "KDCircularProgress iOS";
targetProxy = 3CFA1D9C21720FB70094F95E /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
BC5B0C201D92F75600B43506 /* Main.storyboard */ = {
isa = PBXVariantGroup;
@@ -243,24 +208,15 @@
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_SUSPICIOUS_MOVES = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
@@ -301,24 +257,15 @@
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_SUSPICIOUS_MOVES = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
@@ -346,28 +293,24 @@
BC5B0C2C1D92F75600B43506 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = "iOS Example/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.kaandedeoglu.KDCircularProgress.iOS-Example";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
SWIFT_VERSION = 3.0;
};
name = Debug;
};
BC5B0C2D1D92F75600B43506 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = "iOS Example/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.kaandedeoglu.KDCircularProgress.iOS-Example";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
SWIFT_VERSION = 3.0;
};
name = Release;
};
@@ -14,7 +14,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return true
}
+2 -2
View File
@@ -1,13 +1,13 @@
Pod::Spec.new do |s|
s.name = 'KDCircularProgress'
s.version = '1.5.4'
s.version = '1.5.2'
s.license = 'MIT'
s.summary = 'A circular progress view with gradients written in Swift'
s.homepage = 'https://github.com/kaandedeoglu/KDCircularProgress'
s.authors = { 'Kaan Dedeoglu' => 'kaandedeoglu@me.com' }
s.source = { :git => 'https://github.com/kaandedeoglu/KDCircularProgress.git', :tag => s.version }
s.ios.deployment_target = '9.0'
s.ios.deployment_target = '8.0'
s.source_files = 'KDCircularProgress/*.swift'
s.requires_arc = true
+6 -60
View File
@@ -93,22 +93,20 @@
BC5B0BD91D92F42D00B43506 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1000;
LastUpgradeCheck = 0800;
TargetAttributes = {
BC5B0BE71D92F4FA00B43506 = {
CreatedOnToolsVersion = 8.0;
LastSwiftMigration = 1020;
ProvisioningStyle = Automatic;
};
};
};
buildConfigurationList = BC5B0BDC1D92F42D00B43506 /* Build configuration list for PBXProject "KDCircularProgress" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = en;
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = BC5B0BD81D92F42D00B43506;
productRefGroup = BC5B0BE91D92F4FA00B43506 /* Products */;
@@ -145,65 +143,13 @@
BC5B0BDD1D92F42D00B43506 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
ONLY_ACTIVE_ARCH = YES;
};
name = Debug;
};
BC5B0BDE1D92F42D00B43506 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
};
name = Release;
@@ -231,7 +177,7 @@
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
@@ -266,7 +212,7 @@
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
SWIFT_VERSION = 3.0;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
@@ -296,7 +242,7 @@
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
@@ -324,7 +270,7 @@
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_VERSION = 5.0;
SWIFT_VERSION = 3.0;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
VERSIONING_SYSTEM = "apple-generic";
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1000"
LastUpgradeVersion = "0800"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
+1 -1
View File
@@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.5.4</string>
<string>1.5.2</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSPrincipalClass</key>
+1 -1
View File
@@ -2,7 +2,7 @@
// KDCircularProgress iOS.h
// KDCircularProgress iOS
//
// Copyright (c) 2019 Kaan Dedeoglu. All rights reserved.
// Created by Kaan Dedeoglu on 9/21/16.
//
//
+71 -45
View File
@@ -8,33 +8,31 @@
import UIKit
@objc public enum KDCircularProgressGlowMode: Int {
public enum KDCircularProgressGlowMode {
case forward, reverse, constant, noGlow
}
private extension Comparable {
func clamped(toMinimum minimum: Self, maximum: Self) -> Self {
assert(maximum >= minimum, "Maximum clamp value can't be higher than the minimum")
if self < minimum {
return minimum
} else if self > maximum {
return maximum
} else {
return self
}
}
}
@IBDesignable
@objcMembers
public class KDCircularProgress: UIView, CAAnimationDelegate {
private enum Conversion {
static func degreesToRadians (value:CGFloat) -> CGFloat {
return value * .pi / 180.0
return value * CGFloat.pi / 180.0
}
}
private enum Utility {
static func clamp<T: Comparable>(value: T, minMax: (T, T)) -> T {
let (min, max) = minMax
if value < min {
return min
} else if value > max {
return max
} else {
return value
}
}
static func inverseLerp(value: CGFloat, minMax: (CGFloat, CGFloat)) -> CGFloat {
return (value - minMax.0) / (minMax.1 - minMax.0)
}
@@ -44,7 +42,8 @@ public class KDCircularProgress: UIView, CAAnimationDelegate {
}
static func colorLerp(value: CGFloat, minMax: (UIColor, UIColor)) -> UIColor {
let clampedValue = value.clamped(toMinimum: 0, maximum: 1)
let clampedValue = clamp(value: value, minMax: (0, 1))
let zero = CGFloat(0)
var (r0, g0, b0, a0) = (zero, zero, zero, zero)
@@ -78,12 +77,20 @@ public class KDCircularProgress: UIView, CAAnimationDelegate {
private var radius: CGFloat = 0 {
didSet {
progressLayer.radius = radius
progressLayer.setNeedsDisplay()
}
}
@IBInspectable public var paddingPercentage: CGFloat = 20 {
didSet {
paddingPercentage = Utility.clamp(value: paddingPercentage, minMax: (0, 100))
radius = (frame.size.width/2.0) * ((100 - paddingPercentage) / 100)
}
}
public var progress: Double = 0 {
didSet {
let clampedProgress = progress.clamped(toMinimum: 0, maximum: 1)
let clampedProgress = Utility.clamp(value: progress, minMax: (0, 1))
angle = 360 * clampedProgress
}
}
@@ -132,12 +139,12 @@ public class KDCircularProgress: UIView, CAAnimationDelegate {
@IBInspectable public var glowAmount: CGFloat = 1.0 {//Between 0 and 1
didSet {
glowAmount = glowAmount.clamped(toMinimum: 0, maximum: 1)
glowAmount = Utility.clamp(value: glowAmount, minMax: (0, 1))
progressLayer.glowAmount = glowAmount
}
}
public var glowMode: KDCircularProgressGlowMode = .forward {
@IBInspectable public var glowMode: KDCircularProgressGlowMode = .forward {
didSet {
progressLayer.glowMode = glowMode
}
@@ -145,15 +152,15 @@ public class KDCircularProgress: UIView, CAAnimationDelegate {
@IBInspectable public var progressThickness: CGFloat = 0.4 {//Between 0 and 1
didSet {
progressThickness = progressThickness.clamped(toMinimum: 0, maximum: 1)
progressLayer.progressThickness = progressThickness / 2
progressThickness = Utility.clamp(value: progressThickness, minMax: (0, 1))
progressLayer.progressThickness = progressThickness/2
}
}
@IBInspectable public var trackThickness: CGFloat = 0.5 {//Between 0 and 1
didSet {
trackThickness = trackThickness.clamped(toMinimum: 0, maximum: 1)
progressLayer.trackThickness = trackThickness / 2
trackThickness = Utility.clamp(value: trackThickness, minMax: (0, 1))
progressLayer.trackThickness = trackThickness/2
}
}
@@ -190,6 +197,7 @@ public class KDCircularProgress: UIView, CAAnimationDelegate {
override public init(frame: CGRect) {
super.init(frame: frame)
isUserInteractionEnabled = false
setInitialValues()
refreshValues()
checkAndSetIBColors()
@@ -203,6 +211,7 @@ public class KDCircularProgress: UIView, CAAnimationDelegate {
required public init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
translatesAutoresizingMaskIntoConstraints = false
isUserInteractionEnabled = false
setInitialValues()
refreshValues()
}
@@ -217,11 +226,11 @@ public class KDCircularProgress: UIView, CAAnimationDelegate {
public override func layoutSubviews() {
super.layoutSubviews()
radius = (frame.size.width / 2.0) * 0.8
radius = (frame.size.width/2.0) * ((100 - paddingPercentage) / 100)
}
private func setInitialValues() {
radius = (frame.size.width / 2.0) * 0.8 //We always apply a 20% padding, stopping glows from being clipped
radius = (frame.size.width/2.0) * ((100 - paddingPercentage) / 100)
backgroundColor = .clear
set(colors: .white, .cyan)
}
@@ -235,13 +244,13 @@ public class KDCircularProgress: UIView, CAAnimationDelegate {
progressLayer.gradientRotateSpeed = gradientRotateSpeed
progressLayer.glowAmount = glowAmount
progressLayer.glowMode = glowMode
progressLayer.progressThickness = progressThickness / 2
progressLayer.progressThickness = progressThickness/2
progressLayer.trackColor = trackColor
progressLayer.trackThickness = trackThickness / 2
progressLayer.trackThickness = trackThickness/2
}
private func checkAndSetIBColors() {
let nonNilColors = [IBColor1, IBColor2, IBColor3].compactMap { $0 }
let nonNilColors = [IBColor1, IBColor2, IBColor3].flatMap { $0 }
if !nonNilColors.isEmpty {
set(colors: nonNilColors)
}
@@ -275,7 +284,6 @@ public class KDCircularProgress: UIView, CAAnimationDelegate {
animation.toValue = toAngle
animation.duration = animationDuration
animation.delegate = self
animation.isRemovedOnCompletion = false
angle = toAngle
animationCompletionBlock = completion
@@ -424,8 +432,25 @@ public class KDCircularProgress: UIView, CAAnimationDelegate {
let trackLineWidth = radius * trackThickness
let progressLineWidth = radius * progressThickness
let arcRadius = max(radius - trackLineWidth / 2, radius - progressLineWidth / 2)
ctx.addArc(center: CGPoint(x: width / 2.0, y: height / 2.0), radius: arcRadius, startAngle: 0, endAngle: CGFloat.pi * 2, clockwise: false)
let trackRadius: CGFloat
let progressRadius: CGFloat
if trackLineWidth < progressLineWidth {
trackRadius = radius - trackLineWidth/2 - (progressLineWidth - trackLineWidth)/2
progressRadius = radius - progressLineWidth/2
// trackLineWidth -= (progressLineWidth - trackLineWidth)/2
} else if progressLineWidth < trackLineWidth {
progressRadius = radius - progressLineWidth/2 - (trackLineWidth - progressLineWidth)/2
trackRadius = radius - trackLineWidth/2
// progressLineWidth -= (trackLineWidth - progressLineWidth)/2
} else {
progressRadius = radius - progressLineWidth/2
trackRadius = radius - trackLineWidth/2
}
let arcRadius = max(radius - trackLineWidth/2, radius - progressLineWidth/2)
ctx.addArc(center: CGPoint(x: width/2.0, y: height/2.0), radius: trackRadius, startAngle: 0, endAngle: CGFloat.pi * 2, clockwise: false)
trackColor.set()
ctx.setStrokeColor(trackColor.cgColor)
ctx.setFillColor(progressInsideFillColor.cgColor)
@@ -440,14 +465,14 @@ public class KDCircularProgress: UIView, CAAnimationDelegate {
let fromAngle = Conversion.degreesToRadians(value: CGFloat(-startAngle))
let toAngle = Conversion.degreesToRadians(value: CGFloat((clockwise == true ? -reducedAngle : reducedAngle) - startAngle))
imageCtx?.addArc(center: CGPoint(x: width / 2.0, y: height / 2.0), radius: arcRadius, startAngle: fromAngle, endAngle: toAngle, clockwise: clockwise)
imageCtx?.addArc(center: CGPoint(x: width/2.0, y: height/2.0), radius: progressRadius, startAngle: fromAngle, endAngle: toAngle, clockwise: clockwise)
let glowValue = GlowConstants.glowAmount(forAngle: reducedAngle, glowAmount: glowAmount, glowMode: glowMode, size: width)
if glowValue > 0 {
imageCtx?.setShadow(offset: CGSize(width: -1.0, height: -1.0), blur: glowValue, color: UIColor.black.cgColor)
imageCtx?.setShadow(offset: CGSize.zero, blur: glowValue, color: UIColor.black.cgColor)
}
let linecap: CGLineCap = roundedCorners ? .round : .butt
let linecap: CGLineCap = roundedCorners == true ? .round : .butt
imageCtx?.setLineCap(linecap)
imageCtx?.setLineWidth(progressLineWidth)
imageCtx?.drawPath(using: .stroke)
@@ -459,7 +484,7 @@ public class KDCircularProgress: UIView, CAAnimationDelegate {
ctx.clip(to: bounds, mask: drawMask)
//Gradient - Fill
if !lerpColorMode, colorsArray.count > 1 {
if !lerpColorMode && colorsArray.count > 1 {
let rgbColorsArray: [UIColor] = colorsArray.map { color in // Make sure every color in colors array is in RGB color space
if color.cgColor.numberOfComponents == 2 {
if let whiteValue = color.cgColor.components?[0] {
@@ -481,7 +506,7 @@ public class KDCircularProgress: UIView, CAAnimationDelegate {
} else {
var color: UIColor?
if colorsArray.isEmpty {
color = .white
color = UIColor.white
} else if colorsArray.count == 1 {
color = colorsArray[0]
} else {
@@ -498,10 +523,11 @@ public class KDCircularProgress: UIView, CAAnimationDelegate {
}
}
}
color.map { fillRectWith(context: ctx, color: $0) }
if let color = color {
fillRectWith(context: ctx, color: color)
}
}
ctx.restoreGState()
UIGraphicsPopContext()
}
@@ -513,13 +539,13 @@ public class KDCircularProgress: UIView, CAAnimationDelegate {
private func drawGradientWith(context: CGContext!, componentsArray: [CGFloat]) {
let baseSpace = CGColorSpaceCreateDeviceRGB()
let locations = locationsCache ?? gradientLocationsFor(colorCount: componentsArray.count / 4, gradientWidth: bounds.size.width)
let locations = locationsCache ?? gradientLocationsFor(colorCount: componentsArray.count/4, gradientWidth: bounds.size.width)
let gradient: CGGradient
if let cachedGradient = gradientCache {
gradient = cachedGradient
} else {
guard let cachedGradient = CGGradient(colorSpace: baseSpace, colorComponents: componentsArray, locations: locations, count: componentsArray.count / 4) else {
guard let cachedGradient = CGGradient(colorSpace: baseSpace, colorComponents: componentsArray, locations: locations, count: componentsArray.count/4) else {
return
}
@@ -544,8 +570,8 @@ public class KDCircularProgress: UIView, CAAnimationDelegate {
return []
} else {
let progressLineWidth = radius * progressThickness
let firstPoint = gradientWidth / 2 - (radius - progressLineWidth / 2)
let increment = (gradientWidth - (2 * firstPoint)) / CGFloat(colorCount - 1)
let firstPoint = gradientWidth/2 - (radius - progressLineWidth/2)
let increment = (gradientWidth - (2*firstPoint))/CGFloat(colorCount - 1)
let locationsArray = (0..<colorCount).map { firstPoint + (CGFloat($0) * increment) }
let result = locationsArray.map { $0 / gradientWidth }
-15
View File
@@ -1,15 +0,0 @@
// swift-tools-version:4.2
import PackageDescription
let package = Package(
name: "KDCircularProgress",
products: [
.library(name: "KDCircularProgress", targets: ["KDCircularProgress"])
],
targets: [
.target(
name: "KDCircularProgress",
path: "KDCircularProgress"
)
]
)
+67 -20
View File
@@ -4,8 +4,8 @@
[![License](https://img.shields.io/cocoapods/l/KDCircularProgress.svg?style=flat)](http://cocoapods.org/pods/KDCircularProgress)
[![Platform](https://img.shields.io/cocoapods/p/KDCircularProgress.svg?style=flat)](http://cocoapods.org/pods/KDCircularProgress)
> The master branch is now Swift 4 compatible. For Swift 3: `swift3` branch. Swift 2.3 `swift2.3` branch. Swift 2 `swift2` branch.
>
`KDCircularProgress` master branch is now compatible with Swift 3 (tag 1.5.2). Check Swift 2 (tag 1.4.1) & Swift 2.3 (tag 1.4.5) branches for older versions.
`KDCircularProgress` is a circular progress view written in Swift. It makes it possible to have gradients in the progress view, along with glows and animations.
@@ -63,7 +63,7 @@ carthage update
Just drag `KDCircularProgress.swift` into your project.
## Sample Code
##Sample Code
Below you can see code that creates and sets up a `KCircularProgress` instance. Which gives you a configuration that looks similar to the progress in the example images.
```swift
@@ -83,28 +83,42 @@ view.addSubview(progress)
## Properties
#### progressColors: `[UIColor]`
####progressColors: `[UIColor]`
The colors used to generate the gradient of the progress. You can also set this using the variadic `setColors(UIColor...)` method. A gradient is used only if there is more than one color. A fill is used otherwise. The default is a white fill.
#### angle: `Int`
------
####angle: `Int`
The angle of the progress. Between 0 and 360 (inclusive). Simply change its value in order to change the visual progress of the component. Default is 0.
#### startAngle: `Int`
------
####startAngle: `Int`
The angle at which the progress will begin. Between 0 and 360 (inclusive), however you can pass any negative or positive values and the component will mod them automatically to the required range. Default is 0.
#### clockwise: `Bool`
------
####clockwise: `Bool`
Clockwise if true, Counter-clockwise if false. Default is true.
#### roundedCorners: `Bool`
------
####roundedCorners: `Bool`
When true, the ends of the progress track will be drawn with a half circle radius. Default is false.
#### gradientRotateSpeed: `CGFloat`
------
####gradientRotateSpeed: `CGFloat`
Describes how many times the underlying gradient will perform a 2π rotation for each full cycle of the progress. Integer values recommended. Default is 0.
#### glowAmount: `CGFloat`
------
####glowAmount: `CGFloat`
The intensity of the glow. Between 0 and 1.0. Default is 1.0.
#### glowMode: `KDCircularProgressGlowMode`
------
####glowMode: `KDCircularProgressGlowMode`
- **.forward** - The glow increases proportionaly to the angle. No glow at 0 degrees and full glow at 360 degrees.
- **.reverse** - The glow increases inversely proportional to the angle. Full glow at 0 degrees and no glow at 360 degrees.
@@ -115,72 +129,105 @@ The intensity of the glow. Between 0 and 1.0. Default is 1.0.
The default is **.forward**
#### progressThickness: `CGFloat`
------
####progressThickness: `CGFloat`
The thickness of the progress. Between 0 and 1. Default is 0.4
#### trackThickness: `CGFloat`
------
####trackThickness: `CGFloat`
The thickness of the background track. Between 0 and 1. Default is 0.5
#### trackColor: `UIColor`
------
####trackColor: `UIColor`
The color of the background track. Default is `UIColor.blackColor()`.
#### progressInsideFillColor: `UIColor`
------
####progressInsideFillColor: `UIColor`
The color of the center of the circle. Default is `UIColor.clearColor()`.
## Methods
------
##Methods
```swift
override public init(frame: CGRect)
```
Initialize with a frame. Please only use square frames.
------
```swift
convenience public init(frame:CGRect, colors: UIColor...)
```
Initialize with a frame and the gradient colors.
------
```swift
public func set(colors: UIColor...)
public func set(colors: [UIColor])
```
Set the colors for the progress gradient.
------
```swift
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)?)
```
Animate the progress from the current state to a target value.
------
```swift
public func pauseAnimation()
```
Pause the animation, if any.
------
```swift
public func isAnimating() -> Bool
```
Check if there's an active animation.
## Misc
##Misc
Prefering light colors in the gradients gives better results. As mentioned before, use square frames. Rectangular frames are not tested and might produce unexpected results.
## Contact
##To-Do
- [x] Add example project
- [x] Carthage Support
- [x] CocoaPods Support
- [x] IBDesignable/IBInspectable support
- [x] Adding a `progress` property as an alternative to `angle`
- [ ] Clean up
##Contact
Drop me an email if you want discuss anything further.
[Email](kaandedeoglu@me.com)
## License
##License
The MIT License (MIT)
Copyright (c) 2017 Kaan Dedeoglu
Copyright (c) 2016 Kaan Dedeoglu
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal