Swift 3动画问题

Swift 3 animation issue

我正在实现进度视图,它只是为颜色设置动画。

一切正常,除了 "strokeEnd" 按形状填充并使其闪烁的动画。

视频resource

代码示例:

class MaterialCircularProgressView: UIView {

    let circularLayer = CAShapeLayer()
    let googleColors = [
        UIColor(red:0.282, green:0.522, blue:0.929, alpha:1),
        UIColor(red:0.859, green:0.196, blue:0.212, alpha:1),
        UIColor(red:0.957, green:0.761, blue:0.051, alpha:1),
        UIColor(red:0.235, green:0.729, blue:0.329, alpha:1)
    ]

    let inAnimation: CAAnimation = {
        let animation = CABasicAnimation(keyPath: "strokeEnd")
        animation.fromValue = 0.0
        animation.toValue = 1.0
        animation.duration = 1.0
        animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn)

        return animation
    }()

    let outAnimation: CAAnimation = {
        let animation = CABasicAnimation(keyPath: "strokeStart")
        animation.beginTime = 0.5
        animation.fromValue = 0.0
        animation.toValue = 1.0
        animation.duration = 1.0
        animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)

        return animation
    }()

    let rotationAnimation: CAAnimation = {
        let animation = CABasicAnimation(keyPath: "transform.rotation.z")
        animation.fromValue = 0.0
        animation.toValue = 2 * M_PI
        animation.duration = 2.0
        animation.repeatCount = MAXFLOAT

        return animation
    }()

    var colorIndex : Int = 0

    override init(frame: CGRect) {
        super.init(frame: frame)

        circularLayer.lineWidth = 4.0
        circularLayer.fillColor = nil
        layer.addSublayer(circularLayer)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func layoutSubviews() {
        super.layoutSubviews()

        let center = CGPoint(x: bounds.midX, y: bounds.midY)
        let radius = min(bounds.width, bounds.height) / 2 - circularLayer.lineWidth / 2

        let arcPath = UIBezierPath(arcCenter: CGPoint.zero, radius: radius, startAngle: CGFloat(M_PI_2), endAngle: CGFloat(M_PI_2 + (2 * M_PI)), clockwise: true)

        circularLayer.position = center
        circularLayer.path = arcPath.cgPath

        animateProgressView()
        circularLayer.add(rotationAnimation, forKey: "rotateAnimation")
    }


    func animateProgressView() {

        circularLayer.removeAnimation(forKey: "strokeAnimation")

        circularLayer.strokeColor = googleColors[colorIndex].cgColor

        let strokeAnimationGroup = CAAnimationGroup()
        strokeAnimationGroup.duration = 1.0 + outAnimation.beginTime
        strokeAnimationGroup.repeatCount = 1
        strokeAnimationGroup.animations = [inAnimation, outAnimation]
        strokeAnimationGroup.delegate = self

        circularLayer.add(strokeAnimationGroup, forKey: "strokeAnimation")

        colorIndex += 1;
        colorIndex = colorIndex % googleColors.count;
    }
}


extension MaterialCircularProgressView: CAAnimationDelegate{

    override func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
        if(flag) {
            animateProgressView()
        }
    }

}

您可以通过在初始化程序中将 strokeStart 设置为 outAnimation 的最终值来解决闪烁问题:

circularLayer.strokeStart = 1.0

原因是 CAPropertyAnimation 动画的 属性 的实际值不会自动设置为动画的 toValue,因此它恢复为原始值 0.0 在你的情况下。这就是为什么一段时间会出现一个完整的圆圈。

然而,在下一个圆圈出现之前会有延迟,不确定这是您的意图还是要修复的另一个错误。