Animating UILabel with CoreAnimation / QuartzCore in iOS App

DevZarak picture DevZarak · Sep 21, 2011 · Viewed 8.8k times · Source

I actually stuck on a problem with animating a UILabel in my iOS Application. After 2 days of searching the web for code snippets, still no result.

Every sample I found was about how to animate UIImage, adding it as a subview to UIView by layer. Is there any good example about animating a UILabel? I found a nice solution for a blinking animation by setting the alpha property, like this:

My function:

- (void)blinkAnimation:(NSString *)animationID finished:(BOOL)finished target:(UIView *)target
{
    NSString *selectedSpeed = [[NSUserDefaults standardUserDefaults] stringForKey:@"EffectSpeed"];
    float speedFloat = (1.00 - [selectedSpeed floatValue]);

    [UIView beginAnimations:animationID context:target];
    [UIView setAnimationDuration:speedFloat];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationDidStopSelector:@selector(blinkAnimation:finished:target:)];

    if([target alpha] == 1.0f)
        [target setAlpha:0.0f];
    else
        [target setAlpha:1.0f];
    [UIView commitAnimations];
}

Call my function on the UILabel:

[self blinkAnimation:@"blinkAnimation" finished:YES target:labelView];

But how about a Pulse, or scaling animation?

Answer

sgress454 picture sgress454 · Sep 28, 2011

Unfortunately font size is not an animatable property of NSView. In order to scale a UILabel, you'll need to use more advanced Core Animation techniques, using CAKeyframeAnimation:

  1. Import the QuartzCore.framework into your project, and #import <QuartzCore/QuartzCore.h> in your code.
  2. Create a new CAKeyframeAnimation object that you can add your key frames to.
  3. Create a CATransform3D value defining the scaling operation (don't get confused by the 3D part--you use this object to do any transformations on a layer).
  4. Make the transformation one of the keyframes in the animation by adding it to the CAKeyframeAnimation object using its setValues method.
  5. Set a duration for the animation by calling its setDuration method
  6. Finally, add the animation to the label's layer using [[yourLabelObject layer] addAnimation:yourCAKeyframeAnimationObject forKey:@"anyArbitraryString"]

The final code could look something like this:

// Create the keyframe animation object
CAKeyframeAnimation *scaleAnimation = 
   [CAKeyframeAnimation animationWithKeyPath:@"transform"];

// Set the animation's delegate to self so that we can add callbacks if we want
scaleAnimation.delegate = self;

// Create the transform; we'll scale x and y by 1.5, leaving z alone 
// since this is a 2D animation.
CATransform3D transform = CATransform3DMakeScale(1.5, 1.5, 1); // Scale in x and y

// Add the keyframes.  Note we have to start and end with CATransformIdentity, 
// so that the label starts from and returns to its non-transformed state.
[scaleAnimation setValues:[NSArray arrayWithObjects:
                  [NSValue valueWithCATransform3D:CATransform3DIdentity],
                  [NSValue valueWithCATransform3D:transform],
                  [NSValue valueWithCATransform3D:CATransform3DIdentity],
                  nil]];

// set the duration of the animation
[scaleAnimation setDuration: .5];

// animate your label layer = rock and roll!
[[self.label layer] addAnimation:scaleAnimation forKey:@"scaleText"];

I'll leave the repeating "pulse" animation as an exercise for you: hint, it involves the animationDidStop method!

One other note--the full list of CALayer animatable properties (of which "transform" is one) can be found here. Happy tweening!