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?