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.
In iOS 4 and later, there's a way to do this just using the UIView transition method without needing to import QuartzCore. You can just say:
Objective C
[UIView transitionWithView:button
duration:0.4
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
button.hidden = YES;
}
completion:NULL];
Swift
UIView.transition(with: button, duration: 0.4,
options: .transitionCrossDissolve,
animations: {
button.hidden = false
})
Previous Solution
Michail's solution will work, but it's not actually the best approach.
The problem with alpha fading is that sometimes the different overlapping view layers look weird as they fade out. There are some other alternatives using Core Animation. First include the QuartzCore framework in your app and add #import <QuartzCore/QuartzCore.h>
to your header. Now you can do one of the following:
1) set button.layer.shouldRasterize = YES;
and then use the alpha animation code that Michail provided in his answer. This will prevent the layers from blending weirdly, but has a slight performance penalty, and can make the button look blurry if it's not aligned exactly on a pixel boundary.
Alternatively:
2) Use the following code to animate the fade instead:
CATransition *animation = [CATransition animation];
animation.type = kCATransitionFade;
animation.duration = 0.4;
[button.layer addAnimation:animation forKey:nil];
button.hidden = YES;
The nice thing about this approach is you can crossfade any property of the button even if they aren't animatable (e.g. the text or image of the button), just set up the transition and then set your properties immediately afterwards.
Best Answer
Swift 5
In my case, when I set
button.alpha = 0
, the button interaction stops working, no matter if I setupUIViewAnimationOptionAllowUserInteraction
as an option.Reason
Whenever you define the animation or not, the view's property is applying to view's layer immediately. Because of this, when you set the
view.alpha=0
, you hide theview
completely.Solution
Easy, just reduce
alpha=0.1
(or even0.05
)