From 25885282e26ac99f0d88318929c62acad89e84c7 Mon Sep 17 00:00:00 2001 From: carlo-ev Date: Tue, 3 Jan 2017 00:13:21 -0600 Subject: [PATCH 1/2] everything set for loading animation, just need to tweak animation a little more --- SweetAlert/SweetAlert.swift | 99 ++++++++++++++++++++++++++++++++++--- 1 file changed, 93 insertions(+), 6 deletions(-) diff --git a/SweetAlert/SweetAlert.swift b/SweetAlert/SweetAlert.swift index e501fc5..b10be6c 100644 --- a/SweetAlert/SweetAlert.swift +++ b/SweetAlert/SweetAlert.swift @@ -11,9 +11,20 @@ import UIKit import QuartzCore public enum AlertStyle { - case success,error,warning,none + case success,error,warning,none,loading case customImag(imageFile:String) } +public func ==(left: AlertStyle, right: AlertStyle) -> Bool{ + switch (left,right) { + case (.Success, .Success): return true + case (.Error, .Error): return true + case (.Warning, .Warning): return true + case (.None, .None) return true + case (.Loading, .Loading) return true + case (.CustomImag(let rFile), .CustomImag(let lFile)) where rFile == lFile: return true + default: return false + } +} open class SweetAlert: UIViewController { let kBakcgroundTansperancy: CGFloat = 0.7 @@ -106,7 +117,7 @@ open class SweetAlert: UIViewController { } // Subtitle - if self.subTitleTextView.text.isEmpty == false { + if !self.subTitleTextView.text.isEmpty { let subtitleString = subTitleTextView.text! as NSString let rect = subtitleString.boundingRect(with: CGSize(width: width, height: 0.0), options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSFontAttributeName:subTitleTextView.font!], context: nil) textViewHeight = ceil(rect.size.height) + 10.0 @@ -178,7 +189,7 @@ open class SweetAlert: UIViewController { func closeAlert(_ buttonIndex:Int){ if userAction != nil { - let isOtherButton = buttonIndex == 0 ? true: false + let isOtherButton = buttonIndex == 0 SweetAlertContext.shouldNotAnimate = true userAction!(isOtherButton) SweetAlertContext.shouldNotAnimate = false @@ -255,6 +266,9 @@ open class SweetAlert: UIViewController { case .error: self.animatedView = CancelAnimatedView() + case .loading: + self.animatedView = LoadingAnimatedView() + case .warning: self.animatedView = InfoAnimatedView() @@ -271,7 +285,7 @@ open class SweetAlert: UIViewController { self.subTitleTextView.text = subTitle } buttons = [] - if buttonTitle.isEmpty == false { + if !buttonTitle.isEmpty && !(style == .loading) { let button: UIButton = UIButton(type: UIButtonType.custom) button.setTitle(buttonTitle, for: UIControlState()) button.backgroundColor = buttonColor @@ -280,7 +294,7 @@ open class SweetAlert: UIViewController { buttons.append(button) } - if otherButtonTitle != nil && otherButtonTitle!.isEmpty == false { + if otherButtonTitle != nil && !otherButtonTitle!.isEmpty { let button: UIButton = UIButton(type: UIButtonType.custom) button.setTitle(otherButtonTitle, for: UIControlState()) button.backgroundColor = otherButtonColor @@ -290,7 +304,7 @@ open class SweetAlert: UIViewController { } resizeAndRelayout() - if SweetAlertContext.shouldNotAnimate == true { + if SweetAlertContext.shouldNotAnimate { //Do not animate Alert if self.animatedView != nil { self.animatedView!.animate() @@ -345,6 +359,79 @@ class AnimatableView: UIView { } } +class LoadingAnimatedView: AnimatableView{ + var circleLayer: CAShapeLayer = CAShapeLayer() + private var circlePath: CGPath { + let path = UIBezierPath() + let startAngle: CGFloat = M_PI/2 //2*M_PI//CGFloat((M_PI/2)) + let endAngle: CGFloat = 0 + path.addArcWithCenter(CGPointMake(self.frame.size.width/2.0, self.frame.size.width/2.0), radius: self.frame.size.width/2.0, startAngle: startAngle, endAngle: endAngle, clockwise: true) + return path.CGPath + } + override required init(frame: CGRect) { + super.init(frame: frame) + setupLayers() + } + override func layoutSubviews() { + setupLayers() + } + required init(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + private func setupLayers(){ + circleAnimation.path = circlePath + circleAnimation.fillColor=UIColor.clearColor().CGColor + circleAnimation.strokeColor=UIColor.colorFromRGB(0x2960FF).CGColor + circleAnimation.lineCap=kCALineCapRound + circleAnimation.lineWidth=4 + circleAnimation.frame=CGRect(x: 0, y: 0, width: self.frame.size.width, height: self.frame.size.height) + circleAnimation.position=CGPoint(x: self.frame.size.width/2.0, y: self.frame.size.height/2.0) + layer.addSublayer(circleAnimation) + } + override func animate(){ + let animation=CABasicAnimation(keyPath: "transform.rotation") + animation.duration=2.0 + animation.byValue=NSNumber(double: 2*M_PI ) + animation.repeatCount = Float.infinity + + let shrinkAnimation = CABasicAnimation(keyPath: "strokeStart") + shrinkAnimation.duration=0.75 + shrinkAnimation.removedOnCompletion=false + shrinkAnimation.fromValue=0 + shrinkAnimation.toValue=0.75 + shrinkAnimation.fillMode=kCAFillModeForwards + shrinkAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) + + let moveStartAnimation = CABasicAnimation(keyPath: "strokeStart") + moveStartAnimation.duration=0.75 + moveStartAnimation.removedOnCompletion=false + moveStartAnimation.fromValue=0.75 + moveStartAnimation.toValue=1 + moveStartAnimation.beginTime=0.75 + moveStartAnimation.fillMode=kCAFillModeForwards + moveStartAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) + + let growAnimation = CABasicAnimation(keyPath: "strokeEnd") + growAnimation.duration=1.5 + growAnimation.removedOnCompletion=false + growAnimation.fromValue=0 + growAnimation.toValue=0.75 + growAnimation.beginTime=0.75 + growAnimation.fillMode=kCAFillModeForwards + growAnimation.timingFunction &&= CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) + + + let groupAnimations = CAAnimationGroup() + groupAnimations.animations = [shrinkAnimation,moveStartAnimation,growAnimation] + groupAnimations.repeatCount=Float.infinity + groupAnimations.duration=2.25//4.5 + groupAnimations.fillMode=kCAFillModeForwards + + circleAnimation.addAnimation(groupAnimations, forKey: "drawAnimation") + //circleAnimation.addAnimation(animation, forKey: "rotateAnimation") + } +} + class CancelAnimatedView: AnimatableView { var circleLayer = CAShapeLayer() From 5d4f6139d68b3e46e365e2d6ce1c3c183b0de205 Mon Sep 17 00:00:00 2001 From: carlo-ev Date: Wed, 4 Jan 2017 00:53:21 -0600 Subject: [PATCH 2/2] proper loading animation resembling material loader --- SweetAlert/SweetAlert.swift | 67 +++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 29 deletions(-) diff --git a/SweetAlert/SweetAlert.swift b/SweetAlert/SweetAlert.swift index b10be6c..913301f 100644 --- a/SweetAlert/SweetAlert.swift +++ b/SweetAlert/SweetAlert.swift @@ -14,17 +14,6 @@ public enum AlertStyle { case success,error,warning,none,loading case customImag(imageFile:String) } -public func ==(left: AlertStyle, right: AlertStyle) -> Bool{ - switch (left,right) { - case (.Success, .Success): return true - case (.Error, .Error): return true - case (.Warning, .Warning): return true - case (.None, .None) return true - case (.Loading, .Loading) return true - case (.CustomImag(let rFile), .CustomImag(let lFile)) where rFile == lFile: return true - default: return false - } -} open class SweetAlert: UIViewController { let kBakcgroundTansperancy: CGFloat = 0.7 @@ -285,7 +274,7 @@ open class SweetAlert: UIViewController { self.subTitleTextView.text = subTitle } buttons = [] - if !buttonTitle.isEmpty && !(style == .loading) { + if !buttonTitle.isEmpty { let button: UIButton = UIButton(type: UIButtonType.custom) button.setTitle(buttonTitle, for: UIControlState()) button.backgroundColor = buttonColor @@ -363,8 +352,8 @@ class LoadingAnimatedView: AnimatableView{ var circleLayer: CAShapeLayer = CAShapeLayer() private var circlePath: CGPath { let path = UIBezierPath() - let startAngle: CGFloat = M_PI/2 //2*M_PI//CGFloat((M_PI/2)) - let endAngle: CGFloat = 0 + let startAngle: CGFloat = 0 + let endAngle: CGFloat = 2*M_PI path.addArcWithCenter(CGPointMake(self.frame.size.width/2.0, self.frame.size.width/2.0), radius: self.frame.size.width/2.0, startAngle: startAngle, endAngle: endAngle, clockwise: true) return path.CGPath } @@ -387,6 +376,9 @@ class LoadingAnimatedView: AnimatableView{ circleAnimation.frame=CGRect(x: 0, y: 0, width: self.frame.size.width, height: self.frame.size.height) circleAnimation.position=CGPoint(x: self.frame.size.width/2.0, y: self.frame.size.height/2.0) layer.addSublayer(circleAnimation) + CATransaction.begin() + circleAnimation.strokeStart=0.25 + CATransaction.commit() } override func animate(){ let animation=CABasicAnimation(keyPath: "transform.rotation") @@ -397,38 +389,55 @@ class LoadingAnimatedView: AnimatableView{ let shrinkAnimation = CABasicAnimation(keyPath: "strokeStart") shrinkAnimation.duration=0.75 shrinkAnimation.removedOnCompletion=false - shrinkAnimation.fromValue=0 - shrinkAnimation.toValue=0.75 + shrinkAnimation.fromValue=0.25 + shrinkAnimation.toValue=0.9999 shrinkAnimation.fillMode=kCAFillModeForwards shrinkAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) + let moveToStart = CABasicAnimation(keyPath: "strokeStart") + moveToStart.duration=0.001 + moveToStart.removedOnCompletion=false + moveToStart.fromValue=0 + moveToStart.toValue=0 + moveToStart.beginTime=0.75 + moveToStart.fillMode=kCAFillModeForwards + moveToStart.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) + + let moveEndToStart = CABasicAnimation(keyPath: "stokeEnd") + moveEndToStart.duration=0.001 + moveEndToStart.removedOnCompletion=false + moveEndToStart.fromValue=0 + moveEndToStart.toValue=0.001 + moveEndToStart.beginTime=0.75 + moveEndToStart.fillMode=kCAFillModeForwards + moveEndToStart.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) + let moveStartAnimation = CABasicAnimation(keyPath: "strokeStart") moveStartAnimation.duration=0.75 moveStartAnimation.removedOnCompletion=false - moveStartAnimation.fromValue=0.75 - moveStartAnimation.toValue=1 - moveStartAnimation.beginTime=0.75 + moveStartAnimation.fromValue=0 + moveStartAnimation.toValue=0.25 + moveStartAnimation.beginTime=0.7501 moveStartAnimation.fillMode=kCAFillModeForwards moveStartAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) let growAnimation = CABasicAnimation(keyPath: "strokeEnd") - growAnimation.duration=1.5 + growAnimation.duration=0.75 growAnimation.removedOnCompletion=false - growAnimation.fromValue=0 - growAnimation.toValue=0.75 - growAnimation.beginTime=0.75 + growAnimation.fromValue=0.001 + growAnimation.toValue=1 + growAnimation.beginTime=0.7501 growAnimation.fillMode=kCAFillModeForwards - growAnimation.timingFunction &&= CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) + growAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) - let groupAnimations = CAAnimationGroup() - groupAnimations.animations = [shrinkAnimation,moveStartAnimation,growAnimation] + groupAnimations.animations = [shrinkAnimation,moveEndToStart,moveToStart,growAnimation,moveStartAnimation] groupAnimations.repeatCount=Float.infinity - groupAnimations.duration=2.25//4.5 + groupAnimations.duration=1.5001 groupAnimations.fillMode=kCAFillModeForwards - circleAnimation.addAnimation(groupAnimations, forKey: "drawAnimation") - //circleAnimation.addAnimation(animation, forKey: "rotateAnimation") + circleAnimation.add(groupAnimations, forKey: "drawAnimation") + circleAnimation.add(animation, forKey: "rotateAnimation") } }