2
votes

In my iphone app I have a UIButton that I rotate 180 degrees into view when another UIButton is pressed, then when clicked again the button rotates a further 180 degrees back to where it started.

This all works fine the very first time the complete 360 degree process occurs, but if I try to start from the start again it snaps 180 degrees then tries to rotate it from that point. Can anyone point me in the right direction? Here's my code so far...

showAnimation= [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation"];
                    showAnimation.duration = self.showAnimationDuration;
                    showAnimation.repeatCount = 1;
                    showAnimation.fillMode = kCAFillModeForwards;
                    showAnimation.removedOnCompletion = NO;
                    showAnimation.cumulative = YES;
                    showAnimation.delegate = self;

float currentAngle =[[[rotateMe.layer presentationLayer] valueForKeyPath:@"transform.rotation.z"] floatValue];

//Rotate 180 degrees from current rotation
showAnimation.values = [NSArray arrayWithObjects:       
                        [NSNumber numberWithFloat:currentAngle],
                        [NSNumber numberWithFloat:currentAngle + (0.5 * M_PI)],
                        [NSNumber numberWithFloat:currentAngle + M_PI], nil];

[rotateMe.layer addAnimation:showAnimation forKey:@"show"];

On completion of the animation I then update the rotateMe.transform rotation to the layer's rotation so that it becomes usable.

- (void)animationDidStop:(CAKeyframeAnimation *)anim finished:(BOOL)flag
{
    float currentAngle =[[[self.layer presentationLayer] valueForKeyPath:@"transform.rotation.z"] floatValue];

    NSLog(@"End: %f", currentAngle);
    rotateMe.transform = CGAffineTransformMakeRotation(0);
}

I have achieved the fully working effect with

    [UIView animateWithDuration:1.0f]
        animations:^{
            CGAffineTransform transform = CGAffineTransformRotate(rotateMe.transform, DEGREES_TO_RADIANS(179.999f));
            rotateMe.transform = transform;
        }
     ];

But I'd like to make the animation more complex, hence the CAKeyframeAnimation.

1

1 Answers

8
votes

You could configure the animation to be additive and animate from 0 to 180 degrees if you need all the key frames. If you don't need the different key frames the you can simply do it with a basic animation and the byValue property. The next time the animation is added it rotate 180 more degrees than whatever rotation is on the view.

If you are setting the actual value in the delegate callback then there is no need for fill mode and not removing the animation on completion.

CABasicAnimation *showAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
showAnimation.byValue = M_PI;
showAnimation.duration = self.showAnimationDuration;
showAnimation.delegate = self;

[rotateMe.layer addAnimation:showAnimation forKey:@"show"];

or using a key frame animation (as explained above: make it additive and animate from 0 to 180 degrees).

CAKeyframeAnimation *showAnimation = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation.z"];
showAnimation.additive = YES; // Make the values relative to the current value
showAnimation.values = @[0, /*all your intermediate values here... ,*/ M_PI];
showAnimation.duration = self.showAnimationDuration;
showAnimation.delegate = self;

[rotateMe.layer addAnimation:showAnimation forKey:@"show"];