Question

I need to animate different CATextLayers depending on some conditions. This is why I wrote a method that accepts the layer and animates it. Here it is:

- (void) animateText:(CATextLayer*) text withColor: (CGColorRef) color andDuration: (NSTimeInterval) duration
{
    CABasicAnimation *colorAnimation = [CABasicAnimation
                                        animationWithKeyPath:@"foregroundColor"];
    colorAnimation.duration = duration;
    colorAnimation.fillMode = kCAFillModeForwards;
    colorAnimation.removedOnCompletion = NO;
    colorAnimation.fromValue = (id)[UIColor redColor].CGColor;
    colorAnimation.toValue = (id)[UIColor blackColor].CGColor;
    colorAnimation.timingFunction = [CAMediaTimingFunction
                                     functionWithName:kCAMediaTimingFunctionLinear];
    [text addAnimation:colorAnimation
                     forKey:@"colorAnimation"];

"text" is a CATextLayer created, initialized and added to sublayers in some other method. The problem is this code does not make the "text" layer animate.

(Please, don't pay attention that the method receives the color. I have temporarily put red and black for testing.)

I started testing. If I create a layer within this method and then try to animate this newly created method, it works ok. If I copy-paste the code to the method where all layers are created and try to animate one of them - it works fine too.

But I need to animate different layers at different moments, so I see this function as essential.

Please, explain me what I am doing wrong. Thank you in advance.

UPDATED: Here's how the layers are created and placed onto UIView

//creating 110 text layers

    CGFloat leftPoint = 0;
    CGFloat topPoint = 0;

    for (int i=0; i<11; ++i)
    {
        for (int j=0; j<10; ++j)
        {
            CATextLayer *label = [[CATextLayer alloc] init];
            [label setString:[_labels objectAtIndex:j+(i*10)]];  // _labels contains letters to display
            [label setFrame:CGRectMake(leftPoint, topPoint, _labelWidth, _labelHeight)]; // _labelWidth and _labelHeight are valid numbers
            [label setAlignmentMode:kCAAlignmentCenter];
            [label setForegroundColor:_textColor];   // _textColor is a CGColorRef type
            [label setFont:(__bridge CFTypeRef)(_font.fontName)]; // font is UIFont type
            [label setFontSize:[_font pointSize]];

            [_textViews addObject:label];    // saving to internal array variable
            [[self layer] addSublayer:label];

            leftPoint += _labelWidth;
        }
        leftPoint = 0;
        topPoint += _labelHeight;
    }

If I place a code like this in the same method where I do animating, it works. And it stops working when I pass the layer in the method like this:

for (int i = 0; i<labelsToHighlight.count; ++i) // labelsToHighlight is an array containing indexes of the CATextLayers which I need to animate
        {
            NSUInteger index = [[labelsToHighlight objectAtIndex:i] intValue];
           [self animateText:[_textViews objectAtIndex:index] withColor: _highlightedTextColor andDuration:_redrawAnimationDuration];
        }
Was it helpful?

Solution

It seems I managed to make it work:

Here's the correct method:

- (void) animateText:(CATextLayer*) text fromColor: (CGColorRef) fromColor toColor: (CGColorRef) toColor andDuration: (NSTimeInterval) duration
{
    CABasicAnimation *colorAnimation = [CABasicAnimation
                                        animationWithKeyPath:@"foregroundColor"];
    colorAnimation.duration = duration;
    colorAnimation.fillMode = kCAFillModeForwards;
    colorAnimation.removedOnCompletion = NO;
    colorAnimation.fromValue = (__bridge id)fromColor;
    colorAnimation.toValue = (__bridge id) toColor;
    colorAnimation.timingFunction = [CAMediaTimingFunction
                                     functionWithName:kCAMediaTimingFunctionLinear];


    [text setForegroundColor:toColor]; // This is what I have actually added
    [text addAnimation:colorAnimation forKey:@"colorAnimation"];       

}

But to be fully honest, I don't understand why that line did make it work. I suppose that without resetting foreground color the animation should have blinked and foreground color would return to its initial value. In reality though absolutely nothing happened on the screen. After adding this everything works just fine.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top