NoKey
NoKey

Reputation: 403

Efficient resize the CAShapeLayer if the view grows animatable

I have a UIButton with a CAShapeLayer inside it. This is part of the subclass's code:

private func addBeneathFill(){
    didAddedBeneathFill = true
    let halfBeneathFill = UIBezierPath()
    halfBeneathFill.move(to: CGPoint(x: 0, y: frame.height / 2))
    halfBeneathFill.addCurve(to: CGPoint(x: frame.width, y: frame.height / 2), controlPoint1: CGPoint(x: frame.width / 10, y: frame.height / 2 + frame.height / 10), controlPoint2: CGPoint(x: frame.width,      y: frame.height / 2 + frame.height / 10))
    halfBeneathFill.addLine(to: CGPoint(x: frame.width, y: frame.height))
    halfBeneathFill.addLine(to: CGPoint(x: 0, y: frame.height))
    halfBeneathFill.addLine(to: CGPoint(x: 0, y: frame.height / 2))
    let path = halfBeneathFill.cgPath
    let shapeLayer = CAShapeLayer()
    shapeLayer.path = path
    let fillColor = halfBeneathFillColor.cgColor
    shapeLayer.fillColor = fillColor
    shapeLayer.opacity = 0.3
    layer.insertSublayer(shapeLayer, at: 2)
}

It works great as long as the UIButton does not change in size. When it changes in size, the CAShapeLayer just stays in it's original position. Of course I can run the method again when the UIButton's frame has been changed, but in an animation it looks awful.

How can I correctly animate the CAShapeLayer's size to be always the current size of the UIButton?

Upvotes: 1

Views: 62

Answers (1)

Tomasz Pe
Tomasz Pe

Reputation: 716

You need to recalculate and animate your path on button frame change.

private func animateShapeLayer() {
    let animation = CABasicAnimation(keyPath: "path")
    animation.fromValue = getBezierPath(forFrame: oldFrame)
    animation.toValue = getBezierPath(forFrame: newFrame)
    animation.duration = 1.0
    animation.fillMode = kCAFillModeForwards
    animation.isRemovedOnCompletion = false
    animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)

    shapeLayer.add(animation, forKey: "path")
}

I've tested it, here you have a link to the playground gist and achieved result:

enter image description here

Upvotes: 1

Related Questions