How to animate the textColor of a UILabel?

2019-05-28 10:07发布

问题:

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.

回答1:

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



回答2:

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)


回答3:

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,



回答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];
        }
    });
}


回答5:

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.



回答6:

[UIView transitionWithView:myLabel duration:0.25 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
    label.textColor = [UIColor redColor];
} completion:^(BOOL finished) {
}];

Try :)



回答7:

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)