2

Could you please tell me how to animate the textColor of a UILabel?

For example I would like to change the color from WHITE to RED, then come back to WHITE with a fade-in effect and repeat that about 3 times.

I need this animation because my app gets real time data from the internet and when a value is changed I need to animate this text value to tell the user that it has changed.

Thank you so much.

Jeehut
  • 15,556
  • 7
  • 54
  • 70
Son Nguyen
  • 3,460
  • 4
  • 30
  • 46

7 Answers7

12

The reason that textColor is not animatable is that UILabel uses a regular CALayer instead of a CATextLayer.

To make textColor animatable (as well as text, font, etc.) we can subclass UILabel and make it use a CATextLayer.

This is quite a lot of work, but luckily I already did it :-)

You can find a complete explanation + a drop-in open source replacement for UILabel in this article

adamsiton
  • 3,562
  • 29
  • 34
  • +1: This was very helpful. I tried messaging you on GitHub, but it seems that you haven't set up an email address. The "Adding AUIAnimatableText to your project" section in the readme needs to be updated to include an extra step: "2. Add UIFont+CoreTextExtensions.h + m to your project". Thanks again! – FreeAsInBeer Feb 10 '12 at 14:05
  • There is a much simpler solution available, see [my answer](http://stackoverflow.com/a/30506117/3451975). – Jeehut May 28 '15 at 12:14
8

This is an old question but currently it's definitely possible to animate the text color with a CrossDissolve. Here's how to do it in Swift:

UIView.transition(with: myLabel, duration: 0.3, options: .transitionCrossDissolve, animations: {
    myLabel.textColor = .white
}, completion: nil)
Bart van Kuik
  • 4,082
  • 1
  • 28
  • 50
4

The question was asked long ago, but here goes.

As said above, textColor for UILabel is not animate-able. A useful trick is to dynamically create in code another UILabel, with the same attributes and position, but with a destination color. You animate the alpha of the new UILabel from 0.0 to 1.0, so it appears like the textColor of the original UILabel is animated. You can remove one of the labels when the animation is completed.

Here is an example of a class level method that changes to a different textColor for a short while and changes it back.

+(void)colorizeLabelForAWhile:(UILabel *)label withUIColor:(UIColor *)tempColor animated:(BOOL)animated
{
    // We will:
    //      1) Duplicate the given label as a temporary UILabel with a new color.
    //      2) Add the temp label to the super view with alpha 0.0
    //      3) Animate the alpha to 1.0
    //      4) Wait for awhile.
    //      5) Animate back and remove the temporary label when we are done.

    // Duplicate the label and add it to the superview
    UILabel *tempLabel = [[UILabel alloc] init];
    tempLabel.textColor = tempColor;
    tempLabel.font = label.font;
    tempLabel.alpha = 0;
    tempLabel.textAlignment = label.textAlignment;
    tempLabel.text = label.text;
    [label.superview addSubview:tempLabel];
    tempLabel.frame = label.frame;

    // Reveal the temp label and hide the current label.
    if (animated) [UIView beginAnimations:nil context:nil];
    tempLabel.alpha = 1;
    label.alpha = 0;
    if (animated) [UIView commitAnimations];

    // Wait for while and change it back.
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, FOR_AWHILE_TIME*NSEC_PER_SEC), dispatch_get_main_queue(), ^{
        if (animated) {
            // Change it back animated
            [UIView animateWithDuration:0.5 animations:^{
                // Animate it back.
                label.alpha = 1;
                tempLabel.alpha = 0;
            } completion:^(BOOL finished){
                // Remove the tempLabel view when we are done.
                [tempLabel removeFromSuperview];
            }];
        } else {
            // Change it back at once and remove the tempLabel view.
            label.alpha = 1.0;
            [tempLabel removeFromSuperview];
        }
    });
}
Erwin
  • 4,689
  • 3
  • 29
  • 41
PostPCDev
  • 664
  • 5
  • 8
  • Yes, thans PostPCDev, your answer is what I did :) – Son Nguyen Oct 08 '12 at 07:18
  • This is not a great solution because text is antialiased. There will be weird artifacts near the edges of the text, especially when animating colors with very different brightness. – Kevin Chen Jun 21 '16 at 01:27
4

I'm unsure if textColor is animatable on UILabel directly. But if you use a CATextLayer it will be much easier to get this effect,

Joshua Weinberg
  • 28,320
  • 2
  • 95
  • 90
  • Could you please explain more about this, I am a newbie in Iphone development :) – Son Nguyen Jul 23 '10 at 04:07
  • http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/CoreAnimation_guide/Introduction/Introduction.html Its far too big of a subject to go into it here. – Joshua Weinberg Jul 23 '10 at 04:44
0

There is a simple solution without any subclassing by using the approach from this answer twice.

A possible implementation in Objective-C might look like this:

- (void)blinkTextInLabel:(UILabel *)label toColor:(UIColor *)color
{
    [UIView transitionWithView:label duration:0 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
        // set to background color (change the color if necessary)
        label.textColor = [UIColor whiteColor];
    } completion:^(BOOL finished) {
        [UIView transitionWithView:label duration:0.5f options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
            label.textColor = color;
        } completion:nil];
    }];
}

Then just call the helper method (here: within the same class using a UITableViewCell):

[self blinkTextInLabel:myCell.textLabel toColor:[UIColor redColor]];

This worked for me using iOS 8.3 – it may work on other versions as well since the used method is available since iOS 4.0 but I haven't tested that.

I hope this helps.

Community
  • 1
  • 1
Jeehut
  • 15,556
  • 7
  • 54
  • 70
0
[UIView transitionWithView:myLabel duration:0.25 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
    label.textColor = [UIColor redColor];
} completion:^(BOOL finished) {
}];

Try :)

Nikita Khandelwal
  • 1,731
  • 14
  • 25
0

Thanks to this answer - I achieved this with cross dissolve:

extension UILabel {
    func animateTextColor(to color: UIColor) {
        UIView.transition(with: self,
                          duration: 0.25,
                          options: .transitionCrossDissolve,
                          animations: { [weak self] in
                            self?.textColor = color
        })
    }
}

Usage:

label.animateTextColor(to: .red)
Islam Q.
  • 3,343
  • 2
  • 26
  • 37