2
votes

What I would like to achieve is: to have several UILabels and to be able to sequentially highlight them, by which I mean I would like to change their textColor, fontSize and position. So I have successfully write a demo that takes a group of UIView and highlights them (changes their backgroundColor) sequentially.

Having read Andrew Fuchs's response to the question Best Way to Perform Several Sequential UIView Animations? which referenced Multiple UIView Animations Without Nested Blocks

However, when I substitute UILabel for UIView in my code, it all falls over and their is no animation, the change happens instantly. Can anyone tell me what am I doing wrong? UILabel is a subclass of UIView so I would have expected properties that work in UIView to work in UILabel. In Apple's "View Programming Guide for iOS - Animation" is states that backgroundColor can be animated. So I have gone back to basics, written some test code and discovered that for a UIView I can happily animate its backgroundColor, alpha and center position. Whereas UILabel alpha property and center position can be successfully animated but it backgroundColor and textColor cannot. See: GitHub AnimateSequentially

- (void)viewDidLoad {
    [super viewDidLoad];

    duration = 2.0;
    yOffset = 100.0;
    normalColor = [UIColor lightGrayColor];
    highlightedColor = [UIColor greenColor];
    view1StartPoint = view1.center;
    view2StartPoint = view2.center;
    lable1StartPoint = label1.center;
    lable2StartPoint = label2.center;
    [self resetEverything:nil];
}

- (IBAction)animateViews:(id)sender
{
    [UIView animateWithDuration:duration
                     animations:^{
                         [view1 setBackgroundColor:highlightedColor];       // animates correctly
//                         [view1 setAlpha:0.2];                              // animates correctly
                         CGPoint p = view1.center;
                         p.y -= yOffset;
                         view1.center = p;                                 // animates correctly
                     }
                     completion:^(BOOL finished){
                         [UIView animateWithDuration:duration
                                          animations:^{
                                              [view2 setBackgroundColor:highlightedColor];
//                                              [view2 setAlpha:0.2];
                                              CGPoint p = view2.center;
                                              p.y -= yOffset;
                                              view2.center = p;                                 // animates correctly
                                          }
                                          completion:nil];
                     }
     ];
}

- (IBAction)animateLabelsSimple:(id)sender      // does NOT works sequentially
{
    [UIView animateWithDuration:duration
                     animations:^{
                         [label1 setBackgroundColor:highlightedColor];      // changes instantly
//                         [label1 setTextColor:[UIColor orangeColor]];       // changes instantly
//                         [label1 setAlpha:0.2];                             // animates correctly
                         CGPoint p = label1.center;
                         p.y -= yOffset;
                         label1.center = p;                                 // animates correctly
                     }
                     completion:^(BOOL finished){
                         [UIView animateWithDuration:duration
                                          animations:^{
                                              [label2 setBackgroundColor:highlightedColor];
//                                              [label2 setTextColor:[UIColor orangeColor]];
//                                              [label2 setAlpha:0.2];
                                              CGPoint p = label2.center;
                                              p.y -= yOffset;
                                              label2.center = p;
                                          }
                                          completion:nil];
                     }
     ];
}

- (IBAction)resetEverything:(id)sender
{
    [view1 setBackgroundColor:normalColor];
    [view2 setBackgroundColor:normalColor];
    [label1 setBackgroundColor:normalColor];
    [label2 setBackgroundColor:normalColor];

    [view1 setAlpha:1.0];
    [view2 setAlpha:1.0];
    [label1 setAlpha:1.0];
    [label2 setAlpha:1.0];

    [label1 setTextColor:[UIColor blackColor]];
    [label2 setTextColor:[UIColor blackColor]];

    view1.center = view1StartPoint;
    view2.center = view2StartPoint;
    label1.center = lable1StartPoint;
    label2.center = lable2StartPoint;
}

I have looked at the GitHub Chameleon project and seen how UIView class method "animateWithDuration" is probably implemented:

+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion
{
    [self _beginAnimationsWithOptions:options | UIViewAnimationOptionTransitionNone];
    [self setAnimationDuration:duration];
    [self setAnimationDelay:delay];
    [self _setAnimationCompletionBlock:completion];

    animations();

    [self commitAnimations];
}

So do I have to subclass UILabel and override the animateWithDuration method? Or what's the best method?

1
Hah. Good spot. I'll have to try this when I get home. I've animated bgColor of views many times but can't remember if I've done a label. Will try this out myself.Fogmeister

1 Answers

0
votes

you can try this https://stackoverflow.com/a/20892927/4030971 to change uilabel color with animation. above you have implemented already this but need some changes.also you can try this

[UIView animateWithDuration:duration animations:^{
     [view1 setBackgroundColor:highlightedColor];       
     [view1 setAlpha:0.2];
     [label setAlpha:0.0];                             
     CGPoint p = view1.center;
     p.y -= yOffset;
     view1.center = p;
}completion:^(BOOL finished){
     if(finished){
         [label setBackgroundColor:[UIColor redColor]];
         [UIView animateWithDuration:duration animations:^{
             [view2 setBackgroundColor:highlightedColor];
             [view2 setAlpha:0.2];
             [label setAlpha:1.0];
             CGPoint p = view2.center;
             p.y -= yOffset;
             view2.center = p;
         }completion:nil];
}];

you can write your label color changing code while its alpha is 0 and after that you can animate the label by making alpha 1. color change code will be after checking of "if finished" and before "next animation" starting block.