How to animate the background color of a UILabel?

This looks like it should work, but doesn't. The color turns green at once.

self.labelCorrection.backgroundColor = [UIColor whiteColor];
[UIView animateWithDuration:2.0 animations:^{
    self.labelCorrection.backgroundColor = [UIColor greenColor];
}];

Solution 1:

I can't find it documented anywhere, but it appears the backgroundColor property of UILabel is not animatable, as your code works fine with a vanilla UIView. This hack appears to work, however, as long as you don't set the background color of the label view itself:

#import <QuartzCore/QuartzCore.h>

...

theLabel.layer.backgroundColor = [UIColor whiteColor].CGColor;

[UIView animateWithDuration:2.0 animations:^{
    theLabel.layer.backgroundColor = [UIColor greenColor].CGColor;
} completion:NULL];

Solution 2:

Swift

  1. (important) Set the UILabel's background color to clear (either in IB or in code). For example:

    override func viewDidLoad() {
        super.viewDidLoad()
    
        myLabel.backgroundColor = UIColor.clear
    }
    
  2. Animate the layer background color.

    @IBAction func animateButtonTapped(sender: UIButton) {
    
        UIView.animate(withDuration: 1.0, animations: {
            self.myLabel.layer.backgroundColor = UIColor.red.cgColor
        })
    }
    

Note that CGColor is added after the UIColor.

Result

enter image description here

Solution 3:

Swift 3

To animate your label background color from white to green, set up your label like this:

self.labelCorrection.backgroundColor = UIColor.clear
self.labelCorrection.layer.backgroundColor = UIColor.white.cgColor

Animate like this:

UIView.animate(withDuration: 2.0) { 
    self.labelCorrection.layer.backgroundColor = UIColor.green.cgColor
}

To go back to the original state, so you can animate again, make sure you remove animations:

self.labelCorrection.layer.backgroundColor = UIColor.white.cgColor
self.labelCorrection.layer.removeAllAnimations()

Solution 4:

You CAN animate it, but I had to first set it (programmatically) to clearColor for some reason. Without that, the animation either didn't work or wasn't visible.

I am animating the background color of a UILabel in a custom table cell. Here is the code in the willDisplayCell method. I wouldn't try to set the animation in cellForRow, since a lot of the layout gets tinkered with by the table.

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
        ((RouteListCell *)cell).name.backgroundColor = [UIColor clearColor];
        [((RouteListCell *)cell).name backgroundGlowAnimationFromColor:[UIColor whiteColor] toColor:[UIColor redColor] clearAnimationsFirst:YES];
}

Here's my animation routine:

-(void) backgroundGlowAnimationFromColor:(UIColor *)startColor toColor:(UIColor *)destColor clearAnimationsFirst:(BOOL)reset;
{
    if (reset)
    {
        [self.layer removeAllAnimations];
    }

    CABasicAnimation *anAnimation = [CABasicAnimation animationWithKeyPath:@"backgroundColor"];
    anAnimation.duration = 1.00;
    anAnimation.repeatCount = HUGE_VAL;
    anAnimation.autoreverses = YES;
    anAnimation.fromValue = (id) startColor.CGColor; // [NSNumber numberWithFloat:1.0];
    anAnimation.toValue = (id) destColor.CGColor; //[NSNumber numberWithFloat:0.10];
    [self.layer addAnimation:anAnimation forKey:@"backgroundColor"];
}