UIView animateWithDuration doesn't animate cornerRadius variation

IosUiviewCore AnimationUiviewanimationCornerradius

Ios Problem Overview


I'm trying to animate the change of the cornerRadius of a UIView instance layer, but the variation of the cornerRadius takes place immediately.

Here's the code:

UIView *view = [[UIView alloc] initWithFrame:CGRectMake(10, 10, 100, 100)];
view.layer.masksToBounds = YES;
view.layer.cornerRadius = 10.0;
[UIView animateWithDuration:1.0 animations:^{
    
    [view.layer.cornerRadius = 0.0;
    
}];

Thanks everybody who is going to give me any tips.

EDIT:

I managed to animate this property using Core Animation, using a CABasicAnimation.

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"cornerRadius"];
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
animation.fromValue = [NSNumber numberWithFloat:10.0f];
animation.toValue = [NSNumber numberWithFloat:0.0f];
animation.duration = 1.0;
[viewToAnimate.layer addAnimation:animation forKey:@"cornerRadius"];
[animation.layer setCornerRadius:0.0];

Ios Solutions


Solution 1 - Ios

tl;dr: Corner radius is not animatable in animateWithDuration:animations:.


What the documentation says about view animations.

As the section on Animations in the "View Programming Guide for iOS" says

>Both UIKit and Core Animation provide support for animations, but the level of support provided by each technology varies. In UIKit, animations are performed using UIView objects

The full list of properties that you can animate using either the older

[UIView beginAnimations:context:];
[UIView setAnimationDuration:];
// Change properties here...
[UIView commitAnimations];

or the newer

[UIView animateWithDuration:animations:];

(that you are using) are:

  • frame
  • bounds
  • center
  • transform (CGAffineTransform, not the CATransform3D)
  • alpha
  • backgroundColor
  • contentStretch

As you can see, cornerRadius is not in the list.

Some confusion

UIView animations is really only meant for animating view properties. What confuses people is that you can also animate the same properties on the layer inside the UIView animation block, i.e. the frame, bounds, position, opacity, backgroundColor. So people see layer animations inside animateWithDuration and believe that they can animate any view property in there.

The same section goes on to say:

>In places where you want to perform more sophisticated animations, or animations not supported by the UIView class, you can use Core Animation and the view’s underlying layer to create the animation. Because view and layer objects are intricately linked together, changes to a view’s layer affect the view itself.

A few lines down you can read the list of Core Animation animatable properties where you see this one:

> * The layer’s border (including whether the layer’s corners are rounded)

So to animate the cornerRadius you need to use Core Animation as you've already said in your updated question (and answer). I just added tried to explain why its so.


Some extra clarification

When people read the documentations that says that animateWithDuration is the recommended way of animating it is easy to believe that it is trying to replace CABasicAnimation, CAAnimationGroup, CAKeyframeAnimation, etc. but its really not. Its replacing the beginAnimations:context: and commitAnimations that you seen above.

Solution 2 - Ios

I use this extension to animate change of corner radius:

extension UIView
{
    func animateCornerRadius(from: CGFloat, to: CGFloat, duration: CFTimeInterval)
    {
        CATransaction.begin()
        let animation = CABasicAnimation(keyPath: "cornerRadius")
        animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear)
        animation.fromValue = from
        animation.toValue = to
        animation.duration = duration
        CATransaction.setCompletionBlock { [weak self] in
            self?.layer.cornerRadius = to
        }
        layer.add(animation, forKey: "cornerRadius")
        CATransaction.commit()
    }
}

Solution 3 - Ios

A corner radius variation can be animated but the only way to do so is to use a CABasicAnimation. Hope this helps somebody out there.

Solution 4 - Ios

You can implement UIView animation as here: http://maniacdev.com/2013/02/ios-uiview-category-allowing-you-to-set-up-customizable-animation-properties

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"cornerRadius"];
animation.duration = DURATION;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
animation.toValue = @(NEW_CORNER_RADIUS);
animation.fillMode = kCAFillModeForwards;
animation.removedOnCompletion = NO;
[view.layer addAnimation:animation forKey:@"setCornerRadius:"];

Solution 5 - Ios

Starting in iOS 10 you can actually animate cornerRadius:

UIViewPropertyAnimator(duration: 3.0, curve: .easeIn) {
    square.layer.cornerRadius = 20
}.startAnimation()

Solution 6 - Ios

Doesn't look like that's one of the animatable properties.

See here for the full list:

http://developer.apple.com/library/ios/#documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/AnimatingViews/AnimatingViews.html

Solution 7 - Ios

You can make this property animatable in +[UIView animateWithDuration:] by implementing -[actionForLayer:forKey] in your view class. See this question for an example of how.

Solution 8 - Ios

CornerRadius property is animatable

working code is below

//layer init

let imageLayer = CALayer() 
imageLayer.frame = CGRect(x: 0, y: 0.0, width: tenPercent, height: tenPercent)
imageLayer.contents = imageNew.cgImage
imageLayer.masksToBounds = true

// animation init

let animationCornerRadius = CABasicAnimation(keyPath: "cornerRadius")
animationCornerRadius.beginTime =  0.01
animationCornerRadius.duration = CFTimeInterval(5)
animationCornerRadius.fromValue = 1
animationCornerRadius.toValue = tenPercent / 2
animationCornerRadius.fillMode = .forwards
animationCornerRadius.isRemovedOnCompletion = false
imageLayer.add(animationCornerRadius , forKey: "cornerRadius")

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionFrancesco PuglisiView Question on Stackoverflow
Solution 1 - IosDavid RönnqvistView Answer on Stackoverflow
Solution 2 - IosChikabuZView Answer on Stackoverflow
Solution 3 - IosFrancesco PuglisiView Answer on Stackoverflow
Solution 4 - IosakaDualityView Answer on Stackoverflow
Solution 5 - IosedwardmpView Answer on Stackoverflow
Solution 6 - IosChrisView Answer on Stackoverflow
Solution 7 - IosSimonView Answer on Stackoverflow
Solution 8 - IosJagveer SinghView Answer on Stackoverflow