iOS 实现Loading效果动画

释放双眼,带上耳机,听听看~!

目标

我们要创建一个登录按钮,点击后有3段动画。
每一段动画:动画从UpLoad蓝色长方形条状按钮到刚开始形成圆形
第二段动画:动画从圆弧显示出来开始,顺时针绘制圆弧,直至圆弧最终绘制完成。
第三段动画:从圆弧绘制完成到圆弧伸展为长方形,在伸展过程中,伴随着颜色变化、圆角动画等基础动画效果。

实现过程

1.圆弧绘制类
包含第二段动画实现,通过动画停止代理方法继续下一段动画

 

import UIKit

protocol CircleDelegate {
    func circleAnimationStop()
}

class CircleView: UIView, CAAnimationDelegate {

    var lineWidth : NSNumber = 3.0
    var strokeColor = UIColor(red: 25/255.0, green: 155/255.0, blue: 200/255.0, alpha: 1.0)
    var circle = CAShapeLayer()
    var delegate : CircleDelegate?
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        let startAngle = CGFloat(Float.pi)/2*3
        let endAngle = CGFloat(Float.pi)/2*7
        let circlePath = UIBezierPath(arcCenter: CGPoint(x: frame.size.width/2, y: frame.size.height/2), radius: frame.size.height/2-2, startAngle: startAngle, endAngle: endAngle, clockwise: true)
        circle.path = circlePath.cgPath
        circle.lineCap = .round
        circle.fillColor = UIColor.clear.cgColor
        circle.lineWidth = CGFloat(lineWidth.floatValue)
        
        self.layer.addSublayer(circle)
    }
 
    required init?(coder: NSCoder) {
        super.init(coder: coder)
    }
    
    func strokeChart() {
        circle.lineWidth = CGFloat(lineWidth.floatValue)
        circle.strokeColor = strokeColor.cgColor
        
        let pathAnimation = CABasicAnimation()
        pathAnimation.keyPath = "strokeEnd"
        pathAnimation.delegate = self
        pathAnimation.duration = 3.0
        pathAnimation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
        pathAnimation.fromValue = 0.0
        pathAnimation.toValue = 1.0
        circle.add(pathAnimation, forKey: nil)
    }
    
    func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
        delegate?.circleAnimationStop()
    }
    
}

2.登录按钮类
包含第一段和第三段动画,通过动画停止代理方法来控制3段动画流程

 

import UIKit

class ButtonView: UIView, CircleDelegate, CAAnimationDelegate {
    let FreshBlue = UIColor(red: 25/255.0, green: 155/255.0, blue: 200/255.0, alpha: 1.0)
    let FreshGreen = UIColor(red: 150/255.0, green: 203/255.0, blue: 25/255.0, alpha: 1.0)
    var view : UIView?
    var viewborder : UIView?
    var button_x : CGFloat = 0
    var button_y : CGFloat = 0
    var button_w : CGFloat = 0
    var button_h : CGFloat = 0
    var label : UILabel?
    var circleView : CircleView?
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        button_x = frame.origin.x
        button_y = frame.origin.y
        button_w = frame.size.width
        button_h = frame.size.height
        
        view = UIView(frame: CGRect(x: 0, y: 0, width: button_w, height: button_h))
        view?.backgroundColor = FreshBlue
        self.addSubview(view!)
        
        viewborder = UIView(frame: CGRect(x: 0, y: 0, width: button_w, height: button_h))
        viewborder?.backgroundColor = .clear
        viewborder?.layer.borderColor = FreshBlue.cgColor
        viewborder?.layer.borderWidth = 3.0
        self.addSubview(viewborder!)
        
        circleView = CircleView(frame: CGRect(x: 0, y: 0, width: button_w, height: button_h))
        circleView?.delegate = self
        self.addSubview(circleView!)
        
        label = UILabel(frame: CGRect(x: 0, y: 0, width: button_w, height: button_h))
        label?.text = "UpLoad"
        label?.textAlignment = .center
        label?.textColor = .white
        label?.font = UIFont.systemFont(ofSize: 20.0)
        self.addSubview(label!)
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
    }
    
    func startAnimation() {
        label?.removeFromSuperview()
        
        let animMakeBigger = CABasicAnimation()
        animMakeBigger.keyPath = "cornerRadius"
        animMakeBigger.fromValue = 5.0
        animMakeBigger.toValue = button_h/2.0
        
        let animBounds = CABasicAnimation()
        animBounds.keyPath = "bounds"
        animBounds.toValue = NSValue(cgRect: CGRect(x: 0, y: 0, width: button_h, height: button_h))
        
        let animAlpha = CABasicAnimation()
        animAlpha.keyPath = "opacity"
        animAlpha.toValue = 0
        
        let animGroup = CAAnimationGroup()
        animGroup.duration = 1
        animGroup.repeatCount = 1
        animGroup.isRemovedOnCompletion = false
        animGroup.fillMode = .forwards
        animGroup.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
        animGroup.animations = [animMakeBigger, animBounds, animAlpha]
        
        let animborder = CABasicAnimation()
        animborder.keyPath = "borderColor"
        animborder.toValue = UIColor(red: 224/255.0, green: 224/255.0, blue: 224/255.0, alpha: 1.0).cgColor
        
        let animGroupAll = CAAnimationGroup()
        animGroupAll.duration = 1
        animGroupAll.repeatCount = 1
        animGroupAll.isRemovedOnCompletion = false
        animGroupAll.fillMode = .forwards
        animGroupAll.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
        animGroupAll.animations = [animMakeBigger, animBounds, animborder]
        animGroupAll.delegate = self
        animGroupAll.setValue("allMyAnimationsBoard", forKey: "groupborderkey")
        
        CATransaction.begin()
        view?.layer.add(animGroup, forKey: nil)
        viewborder?.layer.add(animGroupAll, forKey: nil)
        CATransaction.commit()
    }
    
    func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
        if flag {
            let animType = anim.value(forKey: "groupborderkey")
            let animType1 = anim.value(forKey: "groupborderkey1")
            if animType != nil {
                if (animType as! NSString).isEqual(to: "allMyAnimationsBoard") {
                    circleView?.strokeChart()
                }
            } else if animType1 != nil {
                if (animType1 as! NSString).isEqual(to: "allMyAnimationsBoardspread1") {
                    label = UILabel(frame: CGRect(x: 0, y: 0, width: button_w, height: button_h))
                    label?.text = "Complete"
                    label?.textAlignment = .center
                    label?.textColor = .white
                    label?.font = UIFont.systemFont(ofSize: 20)
                    self.addSubview(label!)
                }
            }
        }
    }
    
    func startAnimationSpread() {
        let animMakeBigger = CABasicAnimation()
        animMakeBigger.keyPath = "cornerRadius"
        animMakeBigger.fromValue = button_h/2.0
        animMakeBigger.toValue = 0
        
        let animBounds = CABasicAnimation()
        animBounds.keyPath = "bounds"
        animBounds.fromValue = NSValue(cgRect: CGRect(x: 0, y: 0, width: button_h, height: button_h))
        animBounds.toValue = NSValue(cgRect: CGRect(x: 0, y: 0, width: button_w, height: button_h))
        
        let animAlpha = CABasicAnimation()
        animAlpha.keyPath = "opacity"
        animAlpha.toValue = 1.0
        
        let animBackground = CABasicAnimation()
        animBackground.keyPath = "backgroundColor"
        animBackground.toValue = FreshGreen.cgColor
        
        let group = CAAnimationGroup()
        group.duration = 1
        group.repeatCount = 1
        group.isRemovedOnCompletion = false
        group.fillMode = .forwards
        group.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
        group.animations = [animMakeBigger, animBounds, animAlpha, animBackground]
        
        let animBorder = CABasicAnimation()
        animBorder.keyPath = "borderColor"
        animBorder.toValue = FreshGreen.cgColor
        
        let allGroup = CAAnimationGroup()
        allGroup.duration = 1
        allGroup.repeatCount = 1
        allGroup.isRemovedOnCompletion = false
        allGroup.fillMode = .forwards
        allGroup.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
        allGroup.animations = [animMakeBigger, animBounds, animAlpha, animBorder]
        allGroup.delegate = self
        allGroup.setValue("allMyAnimationsBoardspread1", forKey: "groupborderkey1")
        
        CATransaction.begin()
        view?.layer.add(group, forKey: nil)
        viewborder?.layer.add(allGroup, forKey: nil)
        CATransaction.commit()
    }
    
    func circleAnimationStop() {
        circleView?.removeFromSuperview()
        self.startAnimationSpread()
    }
    
}

3.Loading按钮使用

 

buttonview = ButtonView(frame: CGRect(x: 100, y: 275, width: 210, height: 70))
        singleTap = UITapGestureRecognizer(target: self, action: #selector(viewAction))
        buttonview?.addGestureRecognizer(singleTap!)
        self.view.addSubview(buttonview!)

 

@objc func viewAction() {
        buttonview?.startAnimation()
    }

效果图

人已赞赏
iOS文章

AFNetworking实现文件断点下载

2019-12-23 17:55:40

iOS文章

Swift的工厂模式

2019-12-23 21:54:05

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
有新消息 消息中心
搜索