I have a progress method 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
}
}
I am trying to make progress bar progress in an animated way. But when I call progress(100)
, it's simply rendering the bar without animation.
How can I fix it?
Update: Created MCVE as per Rob's suggestion: https://github.com/utkarsh2012/ProgressBarTest . I expect the progress bar to animate from width=0 to width=x (say 60)
Looks similar to this problem CABasicAnimation with CALayer path doesn't animate
The
progress
method originally shown in your question is fine. The problem is in how you used it. That having been said, let's go through the MCVE.In your MCVE, there were a few things preventing the animation, namely:
The
progress
method was as follows:That is setting the
path
to be the new path, and then animating from that to the new path (i.e. animating to and from the same path). Thus, no animation.Save the old path before changing the
path
to its new "end state" and initiating the animation. Use that saved path as thefromValue
of the animation.The
value
property was callinglayoutSubviews
:Never call
layoutSubviews()
directly.The view controller was doing the following:
Don't try to start animations in
viewDidLoad
. That's too early in the view lifecycle. UseviewDidAppear
(or whatever) instead. Doing this inviewDidLoad
is generally too early in the view lifecycle.Related to that
viewDidLoad
code, you were changing thevalue
of theDetailView
(which triggered the animation) before you've added it to the view hierarchy.See the fixes here https://github.com/robertmryan/ProgressBarTest.