Search code examples
objective-ccore-animation

CAKeyframeAnimation for blinking caret


I'm trying to animate a view into a blinking caret (like in a text editor). I do not want the caret to interpolate; I'm using opacity to show/hide the cursor, and I want it to go straight from 1.0 to 0.0. Here's what I have so far:

CAKeyframeAnimation* blinkAnimation = [CAKeyframeAnimation animationWithKeyPath:@"opacity"];
blinkAnimation.values = @[ @(1.0), @(0.0) ];
blinkAnimation.keyTimes = @[ @0.0, @0.5 ];
blinkAnimation.duration = 1.0;
blinkAnimation.calculationMode = kCAAnimationDiscrete;
blinkAnimation.repeatCount = HUGE_VALF;
blinkAnimation.removedOnCompletion = NO;

For some strange reason, the caret is drawn at full opacity, and is never drawn at zero opacity. However, if I change from blinkAnimation.calculationMode = kCAAnimationDiscrete to blinkAnimation.calculationMode = kCAAnimationLinear, the caret animates! What is going on?!


Solution

  • If the calculationMode is set to kCAAnimationDiscrete, the first value in the array must be 0.0 and the last value must be 1.0. The array should have one more entry than appears in the values array. For example, if there are two values, there should be three key times.

    CAKeyframeAnimation* blinkAnimation = [CAKeyframeAnimation animationWithKeyPath:@"opacity"];
    blinkAnimation.values = @[ @(1.0), @(0.0), @(1.0)];
    blinkAnimation.keyTimes = @[ @0.0, @0.5, @1.0];
    blinkAnimation.duration = 1.0;
    blinkAnimation.calculationMode = kCAAnimationDiscrete;
    blinkAnimation.repeatCount = HUGE_VALF;
    blinkAnimation.removedOnCompletion = NO;