Steve
Steve

Reputation: 303

CABasicAnimation of CATextLayer property foregroundColor & fontSize sometimes fail to work

In my iOS App I want to create the equivalent of a UILabel that can be highlighted in such a way as to briefly draw attention to itself. So I want it to change its color from blue to red at the same time as it pulsates. So I increase and then decrease the fontSize by say 20%, as a consequence I also need to change the AnchorPoint so that it appears to expand outwards equally in all directions from the centre. I have managed to write code that achieves all these goals, only if it executes as I create the object. However, when I call it via an IBAction by pressing a button the colorChange and fontSizeChange have no effect, whilst the anchorPointChange continues to work. I have no idea what I am doing wrong, though the reason for my problem might well be blindingly obvious, I have failed to spot it. I have tried various incarnations of the code, subclassing UIView and using CALayer classes, but to provide a concise example, here I have packaged it all into viewDidLoad.

Any help would be most appreciated.

OSX Yosemite Version 10.10 (14A389), Xcode Version 6.1 (6A1052d), iOS Simulator Version 8.1 (550.3)

#import "ViewController.h"

@interface ViewController ()
@property (strong, nonatomic) CATextLayer *textLayer;
@end

@implementation ViewController
@synthesize textLayer;
float animationDuration;

- (void)viewDidLoad {
    [super viewDidLoad];

    textLayer = [CATextLayer layer];
    [textLayer setString: @"AB"];
    [textLayer setForegroundColor: [UIColor blueColor].CGColor];
    [textLayer setFontSize: 50.0];
    [textLayer setAlignmentMode: kCAAlignmentCenter];
    [textLayer setFrame: CGRectMake(100, 150, 100, 60)];
    [textLayer setPosition: CGPointMake(CGRectGetMidX(textLayer.frame), CGRectGetMidY(textLayer.frame))];
    [textLayer setAnchorPoint: CGPointMake(0.5, 0.5)];
    [[self.view layer] addSublayer:textLayer];

    UIButton *activationButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    activationButton.backgroundColor = [UIColor lightGrayColor];
    activationButton.frame = CGRectMake(130.0, 250.0, 150.0, 30.0);
    [activationButton setTitle:@"Highlight Label" forState:UIControlStateNormal];
    [activationButton addTarget:self action:@selector(highlightLabel:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:activationButton];

    animationDuration = 2.0;
//    [self changeColor];                           // all three methods work perfectly, if called here
//    [self changeFontSize: 50.0 scale: 1.2];
//    [self changeAnchorPointFrom: CGPointMake(0.5, 0.5) to: CGPointMake(0.5, 0.6)];
/*    [self highlightLabel: nil]; */
}

- (IBAction) highlightLabel: (UIButton *) sender {
    NSLog(@" textLayer.string: %@", textLayer.string);
    [self changeColor];                                                                 // Has no effect
    [self changeFontSize: 50.0 scale: 1.2];                                             // Has no effect
    [self changeAnchorPointFrom: CGPointMake(0.5, 0.5) to: CGPointMake(0.5, 0.6)];      // Only this method call works
}

- (void)changeFontSize: (float) fontSize scale: (float)factor
{
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"fontSize"];
    animation.duration = animationDuration;
    animation.removedOnCompletion = NO;
    animation.autoreverses = YES;
    animation.fromValue = @(fontSize);
    animation.toValue = @(fontSize * factor);
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
    [textLayer addAnimation:animation forKey:@"fontSizeAnimation"];
}

- (void)changeAnchorPointFrom: (CGPoint) startPoint to: (CGPoint)endPoint
{
    CABasicAnimation *animation = [CABasicAnimation  animationWithKeyPath:@"anchorPoint"];
    animation.duration = animationDuration;
    animation.removedOnCompletion = NO;
    animation.autoreverses = YES;
    animation.fromValue = [NSValue valueWithCGPoint:startPoint];
    animation.toValue = [NSValue valueWithCGPoint:endPoint];
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
    [textLayer addAnimation:animation forKey:@"anchorPointAnimation"];
}

- (void)changeColor
{
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"foregroundColor"];
    animation.duration = animationDuration * 2;
    animation.fillMode = kCAFillModeForwards;
    animation.removedOnCompletion = NO;
    animation.fromValue = (id)[UIColor blueColor].CGColor;
    animation.toValue = (id)[UIColor redColor].CGColor;
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
    [textLayer addAnimation:animation forKey:@"colorAnimation"];
}

@end

Upvotes: 2

Views: 1094

Answers (1)

gabbler
gabbler

Reputation: 13766

You need to set the final color of the textlayer, try to add this in the end of your highlightLabel method.

[CATransaction begin];
[CATransaction setDisableActions:YES];
[textLayer setForegroundColor: [UIColor redColor].CGColor];
[CATransaction commit];

Upvotes: 2

Related Questions