I'm trying to make an app with chat "bubbles" and I need to animate a transition between each bubble state.
extension UIView {
func makeRoundedCorners(topLeftRad: Double, topRightRad: Double, bottomRightRad: Double, bottomLeftRad: Double) {
let path = UIBezierPath(roundedRect: self.bounds, topLeftRadius: CGFloat(topLeftRad), topRightRadius: CGFloat(topRightRad), bottomRightRadius: CGFloat(bottomRightRad), bottomLeftRadius: CGFloat(bottomLeftRad))
let maskLayer = CAShapeLayer()
maskLayer.path = path.cgPath
let animation = CABasicAnimation(keyPath: "path")
animation.toValue = path.cgPath
animation.duration = 1
maskLayer.add(animation, forKey: "makeRoundedCorners")
self.layer.mask = maskLayer
}
}
extension UIBezierPath {
convenience init(roundedRect rect: CGRect, topLeftRadius r1: CGFloat, topRightRadius r2: CGFloat, bottomRightRadius r3: CGFloat, bottomLeftRadius r4: CGFloat) {
let left = CGFloat(Double.pi)
let up = CGFloat(1.5*Double.pi)
let down = CGFloat(Double.pi / 2)
let right = CGFloat(0.0)
self.init()
addArc(withCenter: CGPoint(x: rect.minX + r1, y: rect.minY + r1), radius: r1, startAngle: left, endAngle: up, clockwise: true)
addArc(withCenter: CGPoint(x: rect.maxX - r2, y: rect.minY + r2), radius: r2, startAngle: up, endAngle: right, clockwise: true)
addArc(withCenter: CGPoint(x: rect.maxX - r3, y: rect.maxY - r3), radius: r3, startAngle: right, endAngle: down, clockwise: true)
addArc(withCenter: CGPoint(x: rect.minX + r4, y: rect.maxY - r4), radius: r4, startAngle: down, endAngle: left, clockwise: true)
close()
}
}
So I wrote a custom UIBeziePath Initializer and then added an extension for UIView as described.
But when I'm trying to update the state of the cell, nothing happens, it's just draw the path instantly. What should I do with that?
I attached some pictures to give an idea what's going on
I got my mistake and replaced the initial path with maskLayer.path = UIBezierPath(roundedRect: self.bounds, cornerRadius: 5).cgPath
But now this thing is happening
The reasons why the animation happens immediately is that the same path is assigned to maskLayer
and is used as the toValue
of the animation.
let maskLayer = CAShapeLayer()
maskLayer.path = path.cgPath // same path used here...
let animation = CABasicAnimation(keyPath: "path")
animation.toValue = path.cgPath // ... as here
animation.duration = 1
maskLayer.add(animation, forKey: "makeRoundedCorners")
self.layer.mask = maskLayer
Since that path is the expected end value of your animation, you need to provide a value to animate from.
Note: the path animation is "undefined" if the two paths have a different number of control points or segment.