views:

459

answers:

3

I'm new to iPhone development, and doing some experimentation with Core Animation. I've run into a small problem regarding the duration of the animation I'm attempting.

Basically, Ive got a view with two subviews, and I'm trying to animate their opacity so that one fades in while the other fades out. Problem is, instead of a gradual fade in/out, the subviews simply switch instantly to/from full/zero opacity. I've tried to adjust the animation duration with CATransaction with no noticable effect. It's also not specific to animating opacity - animating position shows the same problem.

The code I'm using (inside a method of the superview) follows:

CALayer* oldLayer = ((UIView*) [[self subviews] objectAtIndex:0]).layer;
CALayer* newLayer = ((UIView*) [[self subviews] objectAtIndex:1]).layer;

[CATransaction begin];
[CATransaction setAnimationDuration:1.0f];
oldLayer.opacity = 0.0;
newLayer.opacity = 1.0;
[CATransaction commit];

Does anyone have an idea what the problem might be?

+4  A: 

Is there a reason you're using Core Animation over the generic UIView animation wrapper? It's pretty straightforward to do something like this with

UIView *oldView = [[self subviews] objectAtIndex:0];
UIView *newView = [[self subviews] objectAtIndex:1];

[UIView beginAnimations:@"swapViews" context:nil];
[UIView setAnimationDuration:1];
    oldView.alpha = 0;
    newView.alpha = 1;
[UIView commitAnimations];
Noah Witherspoon
Really good question! I've got a feeling there was a reason, but if there was I can't seem to recall it anymore. Was probably something to do with where I was heading with the whole idea. I'll give your way a go though and see what happens. Thanks!
Mac
That did the trick! I'll keep it that way for now, but if I ever figure out why I was doing it the other way and decide to switch back I'll probably be be back to pick your brains some more. :-) Thanks!
Mac
+2  A: 

Do you need to use an explicit CATransaction here?

The docs here imply that you don't.

JBRWilkinson
My first prototype used an implicit animation, but when I first observed the problem I figured it might be worth trying an explicit animation in case that helped. I guess now that I know it doesn't help I can take it out, but I just thought it best to post exactly what I've got at the moment just in case. Thanks though.
Mac
+6  A: 

Noah's solution is the cleanest way to do what you want, but the reason why you're not seeing the animation is that implicit animations are disabled for CALayers that back UIViews. Because nothing is animating, the CATransaction is unable to set the duration for anything.

If you really wanted to perform this animation on the layer, you'd need to set up a manual CABasicAnimation to do this:

CABasicAnimation *opacityAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
opacityAnimation.removedOnCompletion = NO;
opacityAnimation.fillMode = kCAFillModeForwards;

[oldLayer addAnimation:opacityAnimation forKey:@"opacity"];
[newLayer addAnimation:opacityAnimation forKey:@"opacity"];

[CATransaction begin];
[CATransaction setAnimationDuration:1.0f];
oldLayer.opacity = 0.0;
newLayer.opacity = 1.0;
[CATransaction commit];

(Note that I'm not sure if you can re-use the opacity animation here. You might need to create separate instances for each layer.)

Brad Larson
I wish I could double-upvote this. That's really useful to know. Thanks.
Noah Witherspoon
I'm agreeing vehemently with Noah - thanks very much for this! This explains a lot, and may be exactly what I need further down the track. @Noah - I'll give Brad an upvote on your behalf...
Mac