1. Outline a few ways in which the color of UILabel can be changed gradually from one color to another color over a fixed period of time. The examples below will change the color from Red to Blue over 5 seconds.
2. Describe an approach to make the color varied in response to the value of another variable.
Method 1: Using the animation method of UIView
A very simple approach is to use the transitionWithView:duration:option:animations method of UIView.
The following assumes you have a UILabel called 'textLabel' in your storyboard and that you have established an IBOutlet to it. That is, somewhere in your @interface file there should be a line saying something like:
@property (weak, nonatomic) IBOutlet UILabel *textLabel;
(The best way to make sure this is all link up properly is to use the control-drag approach.)
Then you simply add this to viewDidLoad:
[self.textLabel setTextColor:[UIColor redColor]];
And add the following code to viewDidAppear:
[UIView transitionWithView:self.textLabel
duration:5.0
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
[self.textLabel setTextColor:[UIColor blueColor]];
}
completion:nil];
This is it.
Method 2: Using Core Animation CATextLayer
A more complex approach is to use Core Animation CATextLayer.
First, add the QuartzCore framework and then #import it by adding the following to the top of your file (in either the .h or .m)
#import <QuartzCore/QuartzCore.h>
Next, add the following method:
- (void)animateTextLayer
{
CGFloat animationDuration = 5.0;
CATextLayer *textLayer = [CATextLayer layer];
[textLayer setString:@"Foo"];
[textLayer setForegroundColor:[UIColor redColor].CGColor];
[textLayer setFontSize:50];
[textLayer setFrame:CGRectMake(100, 150, 100, 60)];
[[self.view layer] addSublayer:textLayer];
CABasicAnimation *colorAnimation = [CABasicAnimation
animationWithKeyPath:@"foregroundColor"];
colorAnimation.duration = animationDuration;
colorAnimation.fillMode = kCAFillModeForwards;
colorAnimation.removedOnCompletion = NO;
colorAnimation.fromValue = (id)[UIColor redColor].CGColor;
colorAnimation.toValue = (id)[UIColor blueColor].CGColor;
colorAnimation.timingFunction = [CAMediaTimingFunction
functionWithName:kCAMediaTimingFunctionLinear];
[textLayer addAnimation:colorAnimation
forKey:@"colorAnimation"];
}
Finally, call this method in viewDidLoad:
[self animateTextLayer];
The following assumes that the UILabel has been created as described in Method 1 above.
First, create a variable p by adding this under @implementation:
{
CGFloat p;
}
Next, add the following methods:
- (UIColor *)createColorWithColorOne:(UIColor *)colorOne ColorTwo:(UIColor *)colorTwo andProportion:(CGFloat)proportion
{
CGFloat colorOneRed, colorOneGreen, colorOneBlue, colorOneAlpha;
[colorOne getRed:&colorOneRed green:&colorOneGreen blue:&colorOneBlue alpha:&colorOneAlpha];
CGFloat colorTwoRed, colorTwoGreen, colorTwoBlue, colorTwoAlpha;
[colorTwo getRed:&colorTwoRed green:&colorTwoGreen blue:&colorTwoBlue alpha:&colorTwoAlpha];
CGFloat newRed = colorOneRed + (colorTwoRed - colorOneRed) * proportion;
CGFloat newGreen = colorOneGreen + (colorTwoGreen - colorOneGreen) * proportion;
CGFloat newBlue = colorOneBlue + (colorTwoBlue - colorOneBlue) * proportion;
return [UIColor colorWithRed:newRed green:newGreen blue:newBlue alpha:1.0]; // assuming alpha is constant
}
- (void)changeColor:(NSTimer *)timer
{
self.textLabel.textColor = [self createColorWithColorOne:[UIColor redColor]
ColorTwo:[UIColor blueColor]
andProportion:p];
p +=0.1;
if (p >= 1.0) {
[timer invalidate];
timer = nil;
}
}
And in viewDidLoad add:
p = 0;
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.5
target:self
selector:@selector(changeColor:)
userInfo:nil
repeats:YES];
As said above, this changes the color of the label from red to blue in 5 seconds. You can customise the duration and the smoothness of the color transition by altering the TimeInterval of the NSTimer and the increment amount for the variable p in the changeColor: method.
Making the color vary with reference to another variable
A quick word about the method (UIColor *)createColorWithColorOne:(UIColor *)colorOne ColorTwo:(UIColor *)colorTwo andProportion:(CGFloat)proportion. The logic behind it is based on the equation of a line in 3D space. One way to express a color is by reference to its three color components: red, green and blue. These three values can be represented by a point in 3D space. Given two colors we have two points. And with two points we can construct a line, which can be expressed in the form of a parametric equation (this is essentially what the newRed, newGreen, newBlue lines above come down to). A feature of a parametric equation that is most useful here is that it allows us to express the coordinates by reference to another variable, that is, the variable called 'proportion' here. So by changing this vale we can get different color values between colorOne and colorTwo. (Note: proportion is between 0.0 and 1.0 only. When proportion = 0, the color is red; when proportion = 1.0, it is blue.)
The example here simply increment the proportion gradually over a period of time so that the color animates from red to blue. This is not the only use of this method. Animating color changes between two colors over a fixed duration can be achieved using method 1 and 2, which are arguably much simpler too. The method described here allows you to generate a color that lies between two other color by reference to something else. For example, red can represents a maximum temperature and blue can represent a minimum temperature. Using this method you can get a color as the temperature varies between the minimum and maximum.
With a bit more work, the code can be modified to use more than two colors, such that you can gradually transitional between a multitude of colors over a period of time or as show different colors in response to changes in some other variable.