Hidden Property Cannot Be Changed Within an Animation Block

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.

Sample Image

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



Leave a reply



Submit