For some reason this isn\'t working for me:
let color = CABasicAnimation(keyPath: \"borderColor\")
color.fromValue = sender.layer.borderColor;
color.toValue
I don't know why, but for some reason calling:
color.fromValue = sender.layer.borderColor
doesn't work. The color isn't being read correctly or something. I changed it to:
let color = CABasicAnimation(keyPath: "borderColor");
color.fromValue = UIColor.greenColor().CGColor;
color.toValue = UIColor.redColor().CGColor;
color.duration = 2;
color.repeatCount = 1;
sender.layer.addAnimation(color, forKey: "color and width");
And then things started working as expected.
Swift 4 UIView
extension:
extension UIView {
func animateBorderColor(toColor: UIColor, duration: Double) {
let animation:CABasicAnimation = CABasicAnimation(keyPath: "borderColor")
animation.fromValue = layer.borderColor
animation.toValue = toColor.cgColor
animation.duration = duration
layer.add(animation, forKey: "borderColor")
layer.borderColor = toColor.cgColor
}
}
And then just use it by writing:
myView.animateBorderColor(toColor: .red, duration: 0.5)
I created a Swift 4 function extension to CALayer
for this, to which you can pass the starting and ending UIColor
s as well as the duration for the animation:
extension CALayer {
func animateBorderColor(from startColor: UIColor, to endColor: UIColor, withDuration duration: Double) {
let colorAnimation = CABasicAnimation(keyPath: "borderColor")
colorAnimation.fromValue = startColor.cgColor
colorAnimation.toValue = endColor.cgColor
colorAnimation.duration = duration
self.borderColor = endColor.cgColor
self.add(colorAnimation, forKey: "borderColor")
}
Note that for this to work, you should have already set a borderWidth
and then call animateBorderColor
:
yourView.layer.borderWidth = 1.5
yourView.layer.animateBorderColor(from: UIColor.green, to: UIColor.red, withDuration: 2.0)
(Swift 5, Xcode 11, iOS 13)
For anyone who is wanting to change border color and width at the same time, the following code is working for me & the animation looks very smooth. Maybe someone else knows of a way to combine both into one?
let borderColorAnimation: CABasicAnimation = CABasicAnimation(keyPath: "borderColor")
borderColorAnimation.fromValue = layer.borderColor
borderColorAnimation.toValue = toColor.cgColor
borderColorAnimation.duration = animationDuration
layer.add(borderColorAnimation, forKey: "borderColor")
layer.borderColor = toColor.cgColor
let borderWidthAnimation: CABasicAnimation = CABasicAnimation(keyPath: "borderWidth")
borderWidthAnimation.fromValue = layer.borderWidth
borderWidthAnimation.toValue = toWidth
borderWidthAnimation.duration = animationDuration
layer.add(borderWidthAnimation, forKey: "borderWidth")
layer.borderWidth = toWidth
You have to use the same key name. You also forgot to add a border width and color to your layer before animating it. Try like this:
let color = CABasicAnimation(keyPath: "borderColor")
@IBAction func animateBorder(sender: AnyObject) {
color.fromValue = UIColor.greenColor().CGColor
color.toValue = UIColor.redColor().CGColor
color.duration = 2
color.repeatCount = 1
sender.layer.borderWidth = 2
sender.layer.borderColor = UIColor.greenColor().CGColor
sender.layer.addAnimation(color, forKey: "borderColor")
}