CAShapeLayer上的CABasicAnimation不适用于路径更改

时间:2017-05-12 07:05:49

标签: ios swift animation

我有一个进度方法here

func progress(incremented : CGFloat){
    if incremented <= self.bounds.width{
        self.progressLayer.removeFromSuperlayer()
        let originBezierPathProg = UIBezierPath(roundedRect: CGRect(x:0, y:0, width:0, height:self.bounds.height) , cornerRadius: self.viewCornerRadius)
        originBezierPathProg.close()

        let newBezierPathProg = UIBezierPath(roundedRect: CGRect(x:0, y:0, width:incremented, height:self.bounds.height) , cornerRadius: self.viewCornerRadius)
        bezierPathProg.close()

        self.progressLayer.path = originBezierPathProg.cgPath
        self.borderLayer.addSublayer(self.progressLayer)

        let animation = CABasicAnimation(keyPath: "path")
        animation.fromValue = originBezierPathProg.cgPath
        animation.toValue = newBezierPathProg.cgPath
        animation.duration = 1
        self.progressLayer.add(animation, forKey: animation.keyPath)

        self.progressLayer.path = newBezierPathProg.cgPath
    }
}

我正试图以动画的方式取得进展。但是当我致电progress(100)时,它只是简单地渲染条形而没有动画。

我该如何解决?

更新:根据Rob的建议创建了MCVE:https://github.com/utkarsh2012/ProgressBarTest。我希望进度条从width = 0到width = x(比如60)

进行动画处理

看起来类似于此问题CABasicAnimation with CALayer path doesn't animate

1 个答案:

答案 0 :(得分:2)

您问题中最初显示的progress方法很好。问题在于你如何使用它。已经说过了,让我们来看看MCVE。

your MCVE中,有一些阻止动画的事情,即:

  1. progress方法如下:

    func progress(incremented: CGFloat) {
        if incremented <= bounds.width {
            let toPath = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: incremented + 100, height: bounds.height), cornerRadius: viewCornerRadius)
    
            progressLayer.path = toPath.cgPath
            borderLayer.addSublayer(progressLayer)
    
            let animation = CABasicAnimation(keyPath: "path")
            animation.fromValue = self.progressLayer.path
            animation.toValue = toPath.cgPath
            animation.duration = 3
            progressLayer.add(animation, forKey: animation.keyPath)
        }
    }
    

    即将path设置为新路径,然后将其设置为新路径的动画(即,为同一路径设置动画)。因此,没有动画。

    在将path更改为新的“结束状态”并启动动画之前保存旧路径。将保存的路径用作动画的fromValue

  2. value媒体资源正在调用layoutSubviews

    var value: Int? {
        didSet {
            progress(value: value!)
            self.layoutSubviews()
        }
    }
    

    切勿直接致电layoutSubviews()

  3. 视图控制器正在执行以下操作:

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        let view = DetailView(frame: self.view.frame)
        view.value = 60
        self.containerView.addSubview(view)
    }
    

    请勿尝试在viewDidLoad中启动动画。这在视图生命周期中还为时过早。请改用viewDidAppear(或其他)。在viewDidLoad中执行此操作通常在视图生命周期中过早。

  4. 与该viewDidLoad代码相关,在将其添加到视图层次结构之前,您正在更改value(触发动画)的DetailView。 / p>

  5. 请参阅此处的修正https://github.com/robertmryan/ProgressBarTest