Button Top Border Animation

Hi All,

I am very new to swift animations here. I successfully added a top border to a button by creating a class inheriting from UIButton. In this class, I created a new CALayer for the top border and added it as a sublayer to the button.

From here, I wanted to perform an animation on this border to gradually show the border drawing from left to right. I have been very unsuccessful in this and I do not know why. Below is my code.

let topBorder = CALayer()
topBorder.frame = CGRect(x: 0.0, y: 0.0, width: 0.0, height: 2.0)
topBorder.backgroundColor = UIColor.red.cgColor

let animation:CABasicAnimation = CABasicAnimation(keyPath: “frame”)
animation.fromValue = CGRect(x: 0.0, y: 0.0, width: 0.0, height: 4.0)
animation.toValue = CGRect(x: 0.0, y: 0.0, width: bounds.size.width, height: 4.0)
animation.duration = 4.0
topBorder.add(animation, forKey: nil)

layer.addSublayer(topBorder)

I thought that this would be all that I would have to do as I have done something similar to animate the opacity and that worked great. That successful code is shown below.

let animation:CABasicAnimation = CABasicAnimation(keyPath: “opacity”)
animation.fromValue = 0.0
animation.toValue = 1.0
animation.duration = 4.0
topBorder.add(animation, forKey: nil)

Can anyone help me understand where I have gone wrong with the animation of the border drawing from left to right? Thanks.

John

I think you might have success if you animate the bounds, not the frame. The docs say that bounds is animatable, they don’t say the same for frame.

Hi Aeberbach,

Thanks for the suggestion. I tried this and it did animate. It just didn’t want to animate the way I wanted.

I did some more research and I went a different route by trying to animate a CAShapeLayer. This animated in the way that I was hoping for.

let topRect = CAShapeLayer()
topRect.fillColor = UIColor.red.cgColor
let startShape = UIBezierPath(rect: CGRect(x: 0.0, y: 0.0, width: 0.0, height: 4.0)).cgPath
let endShape = UIBezierPath(rect: CGRect(x: 0.0, y: 0.0, width: bounds.size.width, height: 4.0)).cgPath

topRect.path = startShape

let animation:CABasicAnimation = CABasicAnimation(keyPath: “path”)
animation.toValue = endShape
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
animation.fillMode = kCAFillModeBoth
animation.isRemovedOnCompletion = false
animation.duration = 1.0
topRect.add(animation, forKey: animation.keyPath)

John

Great it worked John!