1

In my app I am using UIView subclasses to display all kinds of information. I want this views to appear round, so I set the cornerRadius on the views layer to self.bounds.size.width / 2.

This works as expected, until I try to animate them. I animate my view using the UIView.animateWithDuration, for example:

UIView.animateWithDuration(0.2, animations: { () -> Void in

    self.myView.frame = CGRectInset(self.myView.frame, -20, -20);

}) { (done) -> Void in

}

I would like my view to also update the cornerRadius of the layer in the same animation (or a seperate animation, because the cornerRadius changes aren't animated with the animateWithDuration.

Here is what I already tried:

  • Subclass a CALayer, which draws a circle and just put that on top of MyView.layer.
  • Perform a CABasicAnimation while the UIView.animatewithDuration is running

But all of them result in screwed results, because either the bounds aren't updated yet, or the resize of the added CALayer is done before the other animation is finished. I want it to be a smooth transition.

Wim Haanstra
  • 5,918
  • 5
  • 41
  • 57
  • Try by setting the view's "clip to bound" = Yes – Janmenjaya Dec 19 '14 at 14:25
  • possible duplicate of [UIView animateWithDuration doesn't animate cornerRadius variation](http://stackoverflow.com/questions/5948167/uiview-animatewithduration-doesnt-animate-cornerradius-variation) – Logan Dec 19 '14 at 14:50

2 Answers2

3
func changeBounds()
{
    let animation = CABasicAnimation()
    animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
    animation.fromValue = NSValue(CGRect: self.theView.frame)
    animation.toValue = NSValue(CGRect: CGRectInset(self.theView.frame, 40, 40))
    animation.duration = 1.0
    self.theView.layer.addAnimation(animation, forKey: "bounds")

    CATransaction.begin()
    CATransaction.setDisableActions(true)
    self.theView.layer.frame = CGRectInset(self.theView.frame, 40, 40)
    CATransaction.commit()
}

func changeCornerRadius()
{
    let animation = CABasicAnimation(keyPath:"cornerRadius")
    animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
    animation.fromValue = 0
    animation.toValue = self.theView.frame.size.width/2
    animation.duration = 1.0
    self.theView.layer.addAnimation(animation, forKey: "cornerRadius")
    self.theView.layer.cornerRadius = self.theView.frame.size.width/2
}

This seems to work for me, just call like this.

self.changeBounds()
self.changeCornerRadius()

Set the animation key to "bounds" instead of "frame". Or you can add these two animation to an animation group.

gabbler
  • 13,626
  • 4
  • 32
  • 44
0

You can use this extension to animate corner radius changing.

extension UIView
{
    func addCornerRadiusAnimation(from: CGFloat, to: CGFloat, duration: CFTimeInterval)
    {
        let animation = CABasicAnimation(keyPath:"cornerRadius")
        animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
        animation.fromValue = from
        animation.toValue = to
        animation.duration = duration
        self.layer.addAnimation(animation, forKey: "cornerRadius")
        self.layer.cornerRadius = to
    }
}
ChikabuZ
  • 10,031
  • 5
  • 63
  • 86