Hidden property cannot be changed within an animation block
On iOS 11 and prior, when hiding an arrangedSubview
of a UIStackView
using UIView animation API multiple times, the hidden property values "stack", and it requires setting hidden to false
multiple times before the value actually changes.
At work we decided to use a UIView extension with a workaround method that sets hidden only once for given value.
extension UIView {
// Workaround for the UIStackView bug where setting hidden to true with animation
// mulptiple times requires setting hidden to false multiple times to show the view.
public func workaround_nonRepeatingSetHidden(hidden: Bool) {
if self.hidden != hidden {
self.hidden = hidden
}
}
}
This is definitely a bug in UIKit, check out the sample project that reproduces it clearly.
UIView ignoring setHidden when in animation block
This is a bug in UIStackView.
Here is another question describing the exact same issue I'm having. This is an open radar for this specific issue.
The solution I found was to avoid setting hidden
to the same value twice.
if (subview.hidden) {
subview.hidden = false
}
The transition doesn't work on the .line elements, they change property but the transition is not applied. Is there any ways to enable it?
Remove display: block;
from line 36
Why animation does not work for [hidden] in Angular?
The hidden
attribute does not support animations, since it doesn't make any transition between the two states.
I recently faced the same issue and did this :
animations: [
trigger('contentExpansion', [
state('collapsed', style({height: '0', opacity: 0})),
state('expanded', style({height: '*', opacity: 1})),
transition('collapsed <=> expanded', [
animate('300ms cubic-bezier(0.35, 0, 0.25, 1)')
]),
]),
],
You can notice I used Angular animation states.
In the HTML :
<div class="card-header" (click)="collapsed = !collapsed">
In the component :
@Input() collapsed: boolean = true;
How to add animation while changing the hidden mode of a uiview?
Unfortunately, hidden is not a property that is animatable through UIView animations. I think your best bet may be to use one of the animations @Erik B suggested, or start dabbling with Core Animations which are much more powerful. Take a glance at the documentation for UIView animations and Core Animations.
I achieved something like what your suggesting by using UIView animations to slide the new view from below another view. This made it appear like a drawer sliding out. If you want to do something like that, you need to intercept the touch up inside event and place the animation code there.
- (IBAction)buttonClicked:(id)sender {
[UIView animateWithDuration:0.5
delay:0.0
options:UIViewAnimationCurveEaseOut
animations:^(void) {
self.myView.frame = /* set the frame here */
}
completion:NULL];
}
How can I animate my less from display: block to display: none?
You cannot animate or transition from display: block;
to display: none;
, so you will need to remove this if you wish to animate it.
To ensure it fades and is removed you should animate the visibilty
and opacity
attributes.
Alternatively if you are using jQuery you can use the .fadeOut()
function.
MDN - CSS Visibility
jQuery - fadeOut()
UIView block animation not working
Better use alpha.
UIImageView *iv = self.imageView;
ZGCBubbleView *bubbleView = [[ZGCBubbleView alloc] init];
bubbleView.alpha = 0;
// bubbleView.hidden = YES;
[iv addSubview:bubbleView];
// UIView animation test
[UIView animateWithDuration:2.0
delay:0
usingSpringWithDamping:0.5
initialSpringVelocity:0.5
options:UIViewAnimationOptionAllowAnimatedContent & UIViewAnimationOptionLayoutSubviews
animations:^{
// bubbleView.hidden = NO;
bubbleView.alpha = 1;
//[self.view layoutIfNeeded]; // tried this
}
completion:nil];
UIButton can't be touched while animated with UIView animateWithDuration
The touchable part of the button will not coincide with the button's visible frame when it is being animated.
Internally, the button's frame will be set to the final value from your animation. You should find that you can tap in this area, and it would work.
To hit a moving button, you need to do hit testing on the button's .layer.presentationLayer
property (need to import the QuartzCore framework to do this). This would typically be done in touch handling methods in your view controller.
I am happy to expand on this answer if you need more.
Here is how you would respond to a touch event by hit testing presentation layers. This code is in the view controller subclass that is managing your buttons. When I did this I was interested in the initial touch rather than the touch ending (which is typically when a tap would register) but the principle is the same.
Remember to import the QuartzCore framework and add it to your project.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint touchLocation = [touch locationInView:self.view];
for (UIButton *button in self.buttonsOutletCollection)
{
if ([button.layer.presentationLayer hitTest:touchLocation])
{
// This button was hit whilst moving - do something with it here
break;
}
}
}
Related Topics
iOS Swift - Custom Camera Overlay
Automatically Change Cell Height Based on Content - Swift
How to Fill a Circle Color by Percentage Value
Today Extension with Uicollectionview Different Behaviour Compared to Single View Application
Auto-Sizing Uicollectionview Headers
How to Get All Keys and Values into Separate String Arrays from Nsdictionary in Swift
How to Call Secitemcopymatching in Xcode 7 Beta 4
Swift - Could Not Cast Value of Type 'Uitabbarcontroller'
Resize Inputaccessoryview Dynamically in iOS 8
How Would I Store a Video into Firebase Storage from Swift
Change Ncwidgetdisplaymode Programmatically in iOS10 Widget
Using Cloud Code with the Parse Server and Heroku
(Swift Spritekit) Rotate Sprite in the Direction of Touch
How to Make a Bullet List with Swift
How to Get User Data from Facebook Sdk on iOS
Spritekit/Swift - How to Check Contact of Two Nodes When They Are Already in Contact