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:
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
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;
}];
}];
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With