Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Changing the text of a UILabel makes it reappear when using UIViewKeyframeAnimations

I have a series of animations I want to perform on UILabel so I looked up UIViewKeyframeAnimations added in iOS7.

A simplified version of what i want to do is:

  1. Fade out UILabel with duration 0.5 seconds
  2. Wait 1 second
  3. Fade in UILabel with new text with duration 0.5 seconds

    NSTimeInterval duration = 2;
    [UIView animateKeyframesWithDuration:duration delay:0 options:UIViewKeyframeAnimationOptionAllowUserInteraction | UIViewAnimationOptionOverrideInheritedOptions animations:^{
        [UIView addKeyframeWithRelativeStartTime:0 relativeDuration:0.5/duration animations:^{
            self.label.alpha = 0;
        }];
    
        [UIView addKeyframeWithRelativeStartTime:1.5/duration relativeDuration:0.5/duration animations:^{
            self.label.text = [@(arc4random_uniform(4000)) stringValue];
            self.label.alpha = 1;
        }];
    } completion:nil];
    

The result is that the label text is faded out and the reappears with new text, then faded out again and faded in again.

A video of the result: Animation Failure

Cheers Morten

like image 819
mbogh Avatar asked Dec 05 '25 19:12

mbogh


1 Answers

You state: "The result is that the label text is faded out and the reappears with new text, then faded out again and faded in again.". What I see in the movie however, is that the alpha transition just works as expected, fade out and fade in. The only exception to your desired behaviour is that the text change is already applied as soon as the animation starts, rather than at the beginning of the second keyframe of your animation.

It's important to understand that the code inside the addKeyframeWithRelativeStartTime blocks gets executed as soon as the animateKeyframesWithDuration gets called. Any animatable change (frame, alpha, etc) will be animated. Likewise, anything that is not an automatically animated view property (such as the label's text change) will be visible instantly.

To help illustrate this, try putting an NSLog statement at the beginning of all animation blocks (of both animateKeyframesWithDuration and addKeyframeWithRelativeStartTime), and one in the completion block. You will see that each NSLog except for the one in the completion block has exactly the same log time.

For this exact reason, the code below will work, since the execution of the complete block is postponed until the first animation has finished:

[UIView animateWithDuration:1 animations:^{
    self.label.alpha = 0;
} completion:^(BOOL finished) {
    self.label.text = [@(arc4random_uniform(4000)) stringValue];
    [UIView animateWithDuration:1 animations:^{
        self.label.alpha = 1;
    }];
}];
like image 87
Tiemen Avatar answered Dec 08 '25 09:12

Tiemen



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!