diff --git a/SweetAlert.podspec b/SweetAlert.podspec index d67c285..03cd846 100644 --- a/SweetAlert.podspec +++ b/SweetAlert.podspec @@ -1,11 +1,11 @@ Pod::Spec.new do |s| s.name = "SweetAlert" s.version = "0.1.0" - s.summary = "Thin wrapper around NSURLSession in Swift. Simplifies HTTP requests." - s.homepage = "https://github.com/codestergit/SweetAlert-iOS" + s.summary = "Sweet alert fork by Josue Sierra. Includes loading alerts." + s.homepage = "https://github.com/JosueSierra12/SweetAlert-iOS" s.license = 'MIT' - s.author = {'codestergit' => 'https://github.com/codestergit/SweetAlert-iOS'} - s.source = { :git => 'https://github.com/codestergit/SweetAlert-iOS.git', :tag => "#{s.version}"} + s.author = {'JosueSierra12' => 'https://github.com/JosueSierra12/SweetAlert-iOS'} + s.source = { :git => 'https://github.com/JosueSierra12/SweetAlert-iOS.git', :tag => "#{s.version}"} s.ios.deployment_target = '8.0' s.source_files = 'SweetAlert/*.swift' s.requires_arc = 'true' diff --git a/SweetAlert/SweetAlert.swift b/SweetAlert/SweetAlert.swift index e501fc5..1c725a0 100644 --- a/SweetAlert/SweetAlert.swift +++ b/SweetAlert/SweetAlert.swift @@ -10,8 +10,9 @@ import Foundation import UIKit import QuartzCore + public enum AlertStyle { - case success,error,warning,none + case success,error,warning,none,loading case customImag(imageFile:String) } @@ -36,13 +37,13 @@ open class SweetAlert: UIViewController { var userAction:((_ isOtherButton: Bool) -> Void)? = nil let kFont = "Helvetica" - init() { + public init() { super.init(nibName: nil, bundle: nil) self.view.frame = UIScreen.main.bounds self.view.autoresizingMask = [UIViewAutoresizing.flexibleHeight, UIViewAutoresizing.flexibleWidth] self.view.backgroundColor = UIColor(red:0, green:0, blue:0, alpha:kBakcgroundTansperancy) self.view.addSubview(contentView) - + //Retaining itself strongly so can exist without strong refrence strongSelf = self } @@ -50,7 +51,7 @@ open class SweetAlert: UIViewController { required public init(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + fileprivate func setupContentView() { contentView.backgroundColor = UIColor(white: 1.0, alpha: 1.0) contentView.layer.cornerRadius = 5.0 @@ -58,8 +59,18 @@ open class SweetAlert: UIViewController { contentView.layer.borderWidth = 0.5 contentView.addSubview(titleLabel) contentView.addSubview(subTitleTextView) - contentView.backgroundColor = UIColor.colorFromRGB(0xFFFFFF) - contentView.layer.borderColor = UIColor.colorFromRGB(0xCCCCCC).cgColor + if #available(iOS 11.0, *) { + contentView.backgroundColor = UIColor.init(named: "background") + } else { + contentView.backgroundColor = .white + // Fallback on earlier versions + } //UIColor.colorFromRGB(0xFFFFFF) + if #available(iOS 11.0, *) { + contentView.layer.borderColor = UIColor.init(named: "borderColorSweetAlert")?.cgColor + } else { + contentView.layer.borderColor = UIColor.colorFromRGB(0xCCCCCC).cgColor + // Fallback on earlier versions + } view.addSubview(contentView) } @@ -68,30 +79,40 @@ open class SweetAlert: UIViewController { titleLabel.numberOfLines = 1 titleLabel.textAlignment = .center titleLabel.font = UIFont(name: kFont, size:25) - titleLabel.textColor = UIColor.colorFromRGB(0x575757) + if #available(iOS 11.0, *) { + titleLabel.textColor = UIColor.init(named: "labelColor") + } else { + titleLabel.textColor = .black + // Fallback on earlier versions + }//UIColor.colorFromRGB(0x575757) } - + fileprivate func setupSubtitleTextView() { subTitleTextView.text = "" subTitleTextView.textAlignment = .center subTitleTextView.font = UIFont(name: kFont, size:16) - subTitleTextView.textColor = UIColor.colorFromRGB(0x797979) + if #available(iOS 11.0, *) { + subTitleTextView.textColor = UIColor.init(named: "labelColor") + } else { + subTitleTextView.textColor = .black + // Fallback on earlier versions + }//UIColor.colorFromRGB(0x797979) subTitleTextView.isEditable = false } - + fileprivate func resizeAndRelayout() { let mainScreenBounds = UIScreen.main.bounds self.view.frame.size = mainScreenBounds.size let x: CGFloat = kWidthMargin var y: CGFloat = KTopMargin let width: CGFloat = kContentWidth - (kWidthMargin*2) - + if animatedView != nil { - animatedView!.frame = CGRect(x: (kContentWidth - kAnimatedViewHeight) / 2.0, y: y, width: kAnimatedViewHeight, height: kAnimatedViewHeight) + animatedView!.frame = CGRect(x: (kContentWidth - kAnimatedViewHeight) / 2.0, y: y, width: kAnimatedViewHeight, height: kAnimatedViewHeight) contentView.addSubview(animatedView!) y += kAnimatedViewHeight + kHeightMargin } - + if imageView != nil { imageView!.frame = CGRect(x: (kContentWidth - kAnimatedViewHeight) / 2.0, y: y, width: kAnimatedViewHeight, height: kAnimatedViewHeight) contentView.addSubview(imageView!) @@ -104,23 +125,25 @@ open class SweetAlert: UIViewController { contentView.addSubview(titleLabel) y += kTitleHeight + kHeightMargin } - + + + // 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) + let rect = subtitleString.boundingRect(with: CGSize(width: width, height: 0.0), options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSAttributedStringKey.font:subTitleTextView.font!], context: nil) textViewHeight = ceil(rect.size.height) + 10.0 subTitleTextView.frame = CGRect(x: x, y: y, width: width, height: textViewHeight) contentView.addSubview(subTitleTextView) y += textViewHeight + kHeightMargin } - + var buttonRect:[CGRect] = [] for button in buttons { let string = button.title(for: UIControlState())! as NSString - buttonRect.append(string.boundingRect(with: CGSize(width: width, height:0.0), options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes:[NSFontAttributeName:button.titleLabel!.font], context:nil)) + buttonRect.append(string.boundingRect(with: CGSize(width: width, height:0.0), options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes:[NSAttributedStringKey.font:button.titleLabel!.font], context:nil)) } - + var totalWidth: CGFloat = 0.0 if buttons.count == 2 { totalWidth = buttonRect[0].size.width + buttonRect[1].size.width + kWidthMargin + 40.0 @@ -131,12 +154,12 @@ open class SweetAlert: UIViewController { y += kHeightMargin var buttonX = (kContentWidth - totalWidth ) / 2.0 for i in 0 ..< buttons.count { - - buttons[i].frame = CGRect(x: buttonX, y: y, width: buttonRect[i].size.width + 20.0, height: buttonRect[i].size.height + 10.0) - buttonX = buttons[i].frame.origin.x + kWidthMargin + buttonRect[i].size.width + 20.0 - buttons[i].layer.cornerRadius = 5.0 - self.contentView.addSubview(buttons[i]) - buttons[i].addTarget(self, action: #selector(SweetAlert.pressed(_:)), for: UIControlEvents.touchUpInside) + + buttons[i].frame = CGRect(x: buttonX, y: y, width: buttonRect[i].size.width + 20.0, height: buttonRect[i].size.height + 10.0) + buttonX = buttons[i].frame.origin.x + kWidthMargin + buttonRect[i].size.width + 20.0 + buttons[i].layer.cornerRadius = 5.0 + self.contentView.addSubview(buttons[i]) + buttons[i].addTarget(self, action: #selector(SweetAlert.pressed(_:)), for: UIControlEvents.touchUpInside) } y += kHeightMargin + buttonRect[0].size.height + 10.0 @@ -156,8 +179,8 @@ open class SweetAlert: UIViewController { contentView.frame = CGRect(x: (mainScreenBounds.size.width - kContentWidth) / 2.0, y: (mainScreenBounds.size.height - y) / 2.0, width: kContentWidth, height: y) contentView.clipsToBounds = true } - - open func pressed(_ sender: UIButton!) { + + @objc open func pressed(_ sender: UIButton!) { self.closeAlert(sender.tag) } @@ -178,7 +201,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 @@ -189,14 +212,16 @@ open class SweetAlert: UIViewController { }) { (Bool) -> Void in self.view.removeFromSuperview() self.cleanUpAlert() - + //Releasing strong refrence of itself. self.strongSelf = nil } } + + func cleanUpAlert() { - + if self.animatedView != nil { self.animatedView!.removeFromSuperview() self.animatedView = nil @@ -204,12 +229,12 @@ open class SweetAlert: UIViewController { self.contentView.removeFromSuperview() self.contentView = UIView() } - + open func showAlert(_ title: String) -> SweetAlert { _ = showAlert(title, subTitle: nil, style: .none) return self } - + open func showAlert(_ title: String, subTitle: String?, style: AlertStyle) -> SweetAlert { _ = showAlert(title, subTitle: subTitle, style: style, buttonTitle: "OK") return self @@ -217,11 +242,16 @@ open class SweetAlert: UIViewController { } open func showAlert(_ title: String, subTitle: String?, style: AlertStyle,buttonTitle: String, action: ((_ isOtherButton: Bool) -> Void)? = nil) -> SweetAlert { - _ = showAlert(title, subTitle: subTitle, style: style, buttonTitle: buttonTitle,buttonColor: UIColor.colorFromRGB(0xAEDEF4)) + if #available(iOS 11.0, *) { + _ = showAlert(title, subTitle: subTitle, style: style, buttonTitle: buttonTitle,buttonColor: UIColor.init(named: "buttonColorSweetAlert")!) + } else { + _ = showAlert(title, subTitle: subTitle, style: style, buttonTitle: buttonTitle,buttonColor: UIColor.colorFromRGB(0xAEDEF4)) + // Fallback on earlier versions + } userAction = action return self } - + open func showAlert(_ title: String, subTitle: String?, style: AlertStyle,buttonTitle: String,buttonColor: UIColor,action: ((_ isOtherButton: Bool) -> Void)? = nil) -> SweetAlert { _ = showAlert(title, subTitle: subTitle, style: style, buttonTitle: buttonTitle,buttonColor: buttonColor,otherButtonTitle: nil) @@ -231,74 +261,77 @@ open class SweetAlert: UIViewController { open func showAlert(_ title: String, subTitle: String?, style: AlertStyle,buttonTitle: String,buttonColor: UIColor,otherButtonTitle: String?, action: ((_ isOtherButton: Bool) -> Void)? = nil) -> SweetAlert { - self.showAlert(title, subTitle: subTitle, style: style, buttonTitle: buttonTitle,buttonColor: buttonColor,otherButtonTitle: - otherButtonTitle,otherButtonColor: UIColor.red) - userAction = action - return self + self.showAlert(title, subTitle: subTitle, style: style, buttonTitle: buttonTitle,buttonColor: buttonColor,otherButtonTitle: + otherButtonTitle,otherButtonColor: UIColor.red) + userAction = action + return self } - + open func showAlert(_ title: String, subTitle: String?, style: AlertStyle,buttonTitle: String,buttonColor: UIColor,otherButtonTitle: String?, otherButtonColor: UIColor?,action: ((_ isOtherButton: Bool) -> Void)? = nil) { - userAction = action - let window: UIWindow = UIApplication.shared.keyWindow! - window.addSubview(view) - window.bringSubview(toFront: view) - view.frame = window.bounds - self.setupContentView() - self.setupTitleLabel() - self.setupSubtitleTextView() - - switch style { - case .success: - self.animatedView = SuccessAnimatedView() - - case .error: - self.animatedView = CancelAnimatedView() - - case .warning: - self.animatedView = InfoAnimatedView() - - case let .customImag(imageFile): - if let image = UIImage(named: imageFile) { - self.imageView = UIImageView(image: image) - } - case .none: - self.animatedView = nil + userAction = action + let window: UIWindow = UIApplication.shared.keyWindow! + window.addSubview(view) + window.bringSubview(toFront: view) + view.frame = window.bounds + self.setupContentView() + self.setupTitleLabel() + self.setupSubtitleTextView() + + switch style { + case .success: + self.animatedView = SuccessAnimatedView() + + case .error: + self.animatedView = CancelAnimatedView() + + case .warning: + self.animatedView = InfoAnimatedView() + + case .loading: + self.animatedView = LoadingAnimatedView() + + case let .customImag(imageFile): + if let image = UIImage(named: imageFile) { + self.imageView = UIImageView(image: image) } + case .none: + self.animatedView = nil + } - self.titleLabel.text = title - if subTitle != nil { - self.subTitleTextView.text = subTitle - } - buttons = [] - if buttonTitle.isEmpty == false { - let button: UIButton = UIButton(type: UIButtonType.custom) - button.setTitle(buttonTitle, for: UIControlState()) - button.backgroundColor = buttonColor - button.isUserInteractionEnabled = true - button.tag = 0 - buttons.append(button) - } - - if otherButtonTitle != nil && otherButtonTitle!.isEmpty == false { - let button: UIButton = UIButton(type: UIButtonType.custom) - button.setTitle(otherButtonTitle, for: UIControlState()) - button.backgroundColor = otherButtonColor - button.addTarget(self, action: #selector(SweetAlert.pressed(_:)), for: UIControlEvents.touchUpInside) - button.tag = 1 - buttons.append(button) - } + self.titleLabel.text = title + if subTitle != nil { + self.subTitleTextView.text = subTitle + } + buttons = [] + if !buttonTitle.isEmpty { + let button: UIButton = UIButton(type: UIButtonType.custom) + button.setTitle(buttonTitle, for: UIControlState()) + button.backgroundColor = buttonColor + button.isUserInteractionEnabled = true + button.tag = 0 + buttons.append(button) + } - resizeAndRelayout() - if SweetAlertContext.shouldNotAnimate == true { - //Do not animate Alert - if self.animatedView != nil { - self.animatedView!.animate() - } - } - else { - animateAlert() + if otherButtonTitle != nil && !otherButtonTitle!.isEmpty { + let button: UIButton = UIButton(type: UIButtonType.custom) + button.setTitle(otherButtonTitle, for: UIControlState()) + button.backgroundColor = otherButtonColor + button.addTarget(self, action: #selector(SweetAlert.pressed(_:)), for: UIControlEvents.touchUpInside) + button.tag = 1 + buttons.append(button) + } + + resizeAndRelayout() + if SweetAlertContext.shouldNotAnimate { + //Do not animate Alert + if self.animatedView != nil { + self.animatedView!.animate() } + } + else { + animateAlert() + } } func animateAlert() { @@ -312,24 +345,24 @@ open class SweetAlert: UIViewController { self.contentView.layer.transform = CATransform3DMakeScale(0.9, 0.9, 0.0); UIView.animate(withDuration: 0.2, animations: { () -> Void in self.contentView.layer.transform = CATransform3DMakeScale(1.1, 1.1, 0.0); + }, completion: { (Bool) -> Void in + UIView.animate(withDuration: 0.1, animations: { () -> Void in + self.contentView.layer.transform = CATransform3DMakeScale(0.9, 0.9, 0.0); }, completion: { (Bool) -> Void in UIView.animate(withDuration: 0.1, animations: { () -> Void in - self.contentView.layer.transform = CATransform3DMakeScale(0.9, 0.9, 0.0); - }, completion: { (Bool) -> Void in - UIView.animate(withDuration: 0.1, animations: { () -> Void in - self.contentView.layer.transform = CATransform3DMakeScale(1.0, 1.0, 0.0); - if self.animatedView != nil { - self.animatedView!.animate() - } - - }, completion: { (Bool) -> Void in - - self.contentView.transform = previousTransform - }) - }) - }) - } - + self.contentView.layer.transform = CATransform3DMakeScale(1.0, 1.0, 0.0); + if self.animatedView != nil { + self.animatedView!.animate() + } + + }, completion: { (Bool) -> Void in + + self.contentView.transform = previousTransform + }) + }) + }) + } + fileprivate struct SweetAlertContext { static var shouldNotAnimate = false } @@ -346,7 +379,7 @@ class AnimatableView: UIView { } class CancelAnimatedView: AnimatableView { - + var circleLayer = CAShapeLayer() var crossPathLayer = CAShapeLayer() @@ -359,24 +392,24 @@ class CancelAnimatedView: AnimatableView { circleLayer.transform = t crossPathLayer.opacity = 0.0 } - + override func layoutSubviews() { setupLayers() } - + required init(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } - - fileprivate var outlineCircle: CGPath { + + fileprivate var outlineCircle: CGPath { let path = UIBezierPath() let startAngle: CGFloat = CGFloat((0) / 180.0 * M_PI) //0 let endAngle: CGFloat = CGFloat((360) / 180.0 * M_PI) //360 path.addArc(withCenter: CGPoint(x: self.frame.size.width/2.0, y: self.frame.size.width/2.0), radius: self.frame.size.width/2.0, startAngle: startAngle, endAngle: endAngle, clockwise: false) - + return path.cgPath - } - + } + fileprivate var crossPath: CGPath { let path = UIBezierPath() let factor:CGFloat = self.frame.size.width / 5.0 @@ -384,10 +417,10 @@ class CancelAnimatedView: AnimatableView { path.addLine(to: CGPoint(x: self.frame.size.height/2.0+factor,y: self.frame.size.height/2.0+factor)) path.move(to: CGPoint(x: self.frame.size.height/2.0+factor,y: self.frame.size.height/2.0-factor)) path.addLine(to: CGPoint(x: self.frame.size.height/2.0-factor,y: self.frame.size.height/2.0+factor)) - + return path.cgPath } - + fileprivate func setupLayers() { circleLayer.path = outlineCircle circleLayer.fillColor = UIColor.clear.cgColor; @@ -397,7 +430,7 @@ class CancelAnimatedView: AnimatableView { circleLayer.frame = CGRect(x: 0, y: 0, width: self.frame.size.width, height: self.frame.size.height) circleLayer.position = CGPoint(x: self.frame.size.width/2.0, y: self.frame.size.height/2.0) self.layer.addSublayer(circleLayer) - + crossPathLayer.path = crossPath crossPathLayer.fillColor = UIColor.clear.cgColor; crossPathLayer.strokeColor = UIColor.colorFromRGB(0xF27474).cgColor; @@ -408,12 +441,12 @@ class CancelAnimatedView: AnimatableView { self.layer.addSublayer(crossPathLayer) } - + override func animate() { var t = CATransform3DIdentity; t.m34 = 1.0 / -500.0; t = CATransform3DRotate(t, CGFloat(90.0 * M_PI / 180.0), 1, 0, 0); - + var t2 = CATransform3DIdentity; t2.m34 = 1.0 / -500.0; t2 = CATransform3DRotate(t2, CGFloat(-M_PI), 1, 0, 0); @@ -426,12 +459,12 @@ class CancelAnimatedView: AnimatableView { animation.isRemovedOnCompletion = false animation.fillMode = kCAFillModeForwards self.circleLayer.add(animation, forKey: "transform") - - + + var scale = CATransform3DIdentity; scale = CATransform3DScale(scale, 0.3, 0.3, 0) - + let crossAnimation = CABasicAnimation(keyPath: "transform") crossAnimation.duration = 0.3; crossAnimation.beginTime = CACurrentMediaTime() + time @@ -439,7 +472,7 @@ class CancelAnimatedView: AnimatableView { crossAnimation.timingFunction = CAMediaTimingFunction(controlPoints: 0.25, 0.8, 0.7, 2.0) crossAnimation.toValue = NSValue(caTransform3D:CATransform3DIdentity) self.crossPathLayer.add(crossAnimation, forKey: "scale") - + let fadeInAnimation = CABasicAnimation(keyPath: "opacity") fadeInAnimation.duration = 0.3; fadeInAnimation.beginTime = CACurrentMediaTime() + time @@ -449,42 +482,42 @@ class CancelAnimatedView: AnimatableView { fadeInAnimation.fillMode = kCAFillModeForwards self.crossPathLayer.add(fadeInAnimation, forKey: "opacity") } - + } class InfoAnimatedView: AnimatableView { - + var circleLayer = CAShapeLayer() var crossPathLayer = CAShapeLayer() - + override init(frame: CGRect) { super.init(frame: frame) setupLayers() } - + override func layoutSubviews() { setupLayers() } - + required init(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + var outlineCircle: CGPath { let path = UIBezierPath() let startAngle: CGFloat = CGFloat((0) / 180.0 * M_PI) //0 let endAngle: CGFloat = CGFloat((360) / 180.0 * M_PI) //360 path.addArc(withCenter: CGPoint(x: self.frame.size.width/2.0, y: self.frame.size.width/2.0), radius: self.frame.size.width/2.0, startAngle: startAngle, endAngle: endAngle, clockwise: false) - + let factor:CGFloat = self.frame.size.width / 1.5 path.move(to: CGPoint(x: self.frame.size.width/2.0 , y: 15.0)) path.addLine(to: CGPoint(x: self.frame.size.width/2.0,y: factor)) path.move(to: CGPoint(x: self.frame.size.width/2.0,y: factor + 10.0)) path.addArc(withCenter: CGPoint(x: self.frame.size.width/2.0,y: factor + 10.0), radius: 1.0, startAngle: startAngle, endAngle: endAngle, clockwise: true) - + return path.cgPath } - + func setupLayers() { circleLayer.path = outlineCircle circleLayer.fillColor = UIColor.clear.cgColor; @@ -495,9 +528,9 @@ class InfoAnimatedView: AnimatableView { circleLayer.position = CGPoint(x: self.frame.size.width/2.0, y: self.frame.size.height/2.0) self.layer.addSublayer(circleLayer) } - + override func animate() { - + let colorAnimation = CABasicAnimation(keyPath:"strokeColor") colorAnimation.duration = 1.0; colorAnimation.repeatCount = HUGE @@ -511,26 +544,26 @@ class InfoAnimatedView: AnimatableView { class SuccessAnimatedView: AnimatableView { - + var circleLayer = CAShapeLayer() var outlineLayer = CAShapeLayer() - + override init(frame: CGRect) { super.init(frame: frame) setupLayers() circleLayer.strokeStart = 0.0 circleLayer.strokeEnd = 0.0 } - + required init(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + override func layoutSubviews() { setupLayers() } - + var outlineCircle: CGPath { let path = UIBezierPath() let startAngle: CGFloat = CGFloat((0) / 180.0 * M_PI) //0 @@ -538,7 +571,7 @@ class SuccessAnimatedView: AnimatableView { path.addArc(withCenter: CGPoint(x: self.frame.size.width/2.0, y: self.frame.size.height/2.0), radius: self.frame.size.width/2.0, startAngle: startAngle, endAngle: endAngle, clockwise: false) return path.cgPath } - + var path: CGPath { let path = UIBezierPath() let startAngle:CGFloat = CGFloat((60) / 180.0 * M_PI) //60 @@ -548,12 +581,12 @@ class SuccessAnimatedView: AnimatableView { path.addLine(to: CGPoint(x: 85.0 - 20.0, y: 30.0 - 20.0)) return path.cgPath } - - + + func setupLayers() { - + outlineLayer.position = CGPoint(x: 0, - y: 0); + y: 0); outlineLayer.path = outlineCircle outlineLayer.fillColor = UIColor.clear.cgColor; outlineLayer.strokeColor = UIColor(red: 150.0/255.0, green: 216.0/255.0, blue: 115.0/255.0, alpha: 1.0).cgColor; @@ -561,9 +594,9 @@ class SuccessAnimatedView: AnimatableView { outlineLayer.lineWidth = 4; outlineLayer.opacity = 0.1 self.layer.addSublayer(outlineLayer) - + circleLayer.position = CGPoint(x: 0, - y: 0); + y: 0); circleLayer.path = path circleLayer.fillColor = UIColor.clear.cgColor; circleLayer.strokeColor = UIColor(red: 150.0/255.0, green: 216.0/255.0, blue: 115.0/255.0, alpha: 1.0).cgColor; @@ -576,7 +609,7 @@ class SuccessAnimatedView: AnimatableView { ] self.layer.addSublayer(circleLayer) } - + override func animate() { let strokeStart = CABasicAnimation(keyPath: "strokeStart") let strokeEnd = CABasicAnimation(keyPath: "strokeEnd") @@ -586,7 +619,7 @@ class SuccessAnimatedView: AnimatableView { strokeEnd.duration = 10.0*factor let timing = CAMediaTimingFunction(controlPoints: 0.3, 0.6, 0.8, 1.2) strokeEnd.timingFunction = timing - + strokeStart.fromValue = 0.0 strokeStart.toValue = 0.68 strokeStart.duration = 7.0*factor @@ -598,7 +631,7 @@ class SuccessAnimatedView: AnimatableView { self.circleLayer.add(strokeEnd, forKey: "strokeEnd") self.circleLayer.add(strokeStart, forKey: "strokeStart") } - + } extension UIColor { @@ -612,3 +645,96 @@ extension UIColor { } } +class LoadingAnimatedView: AnimatableView{ + var circleLayer: CAShapeLayer = CAShapeLayer() + private var circlePath: CGPath { + let path = UIBezierPath() + let startAngle: CGFloat = 0 + let endAngle: CGFloat = CGFloat(((2.0*M_PI) as! NSNumber).floatValue) + path.addArc(withCenter: (CGPoint(x:self.frame.size.width/2.0, y: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(){ + + circleLayer.path = circlePath + circleLayer.fillColor=UIColor.clear.cgColor + circleLayer.strokeColor = UIColor.red.cgColor + circleLayer.lineCap=kCALineCapRound + circleLayer.lineWidth=4 + circleLayer.frame=CGRect(x: 0, y: 0, width: self.frame.size.width, height: self.frame.size.height) + circleLayer.position=CGPoint(x: self.frame.size.width/2.0, y: self.frame.size.height/2.0) + layer.addSublayer(circleLayer) + CATransaction.begin() + circleLayer.strokeStart=0.25 + CATransaction.commit() + } + override func animate(){ + let animation=CABasicAnimation(keyPath: "transform.rotation") + animation.duration=2.0 + animation.byValue=NSNumber(value: 2*M_PI ) + animation.repeatCount = Float.infinity + + let shrinkAnimation = CABasicAnimation(keyPath: "strokeStart") + shrinkAnimation.duration=0.75 + shrinkAnimation.isRemovedOnCompletion=false + 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.isRemovedOnCompletion=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.isRemovedOnCompletion=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.isRemovedOnCompletion=false + 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=0.75 + growAnimation.isRemovedOnCompletion=false + growAnimation.fromValue=0.001 + growAnimation.toValue=1 + growAnimation.beginTime=0.7501 + growAnimation.fillMode=kCAFillModeForwards + growAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) + + let groupAnimations = CAAnimationGroup() + groupAnimations.animations = [shrinkAnimation,moveEndToStart,moveToStart,growAnimation,moveStartAnimation] + groupAnimations.repeatCount=Float.infinity + groupAnimations.duration=1.5001 + groupAnimations.fillMode=kCAFillModeForwards + + circleLayer.add(groupAnimations, forKey: "drawAnimation") + circleLayer.add(animation, forKey: "rotateAnimation") + } +} \ No newline at end of file