views:

1592

answers:

2

I'm doing this to learn how to work with Core Animation animatable properties on iPhone (not to learn how to crossfade images, per se).

Reading similar questions on SO leads me to believe it can be done by animating the .contents property of the UIImageView's layer like so:

UIImage *image1 = [UIImage imageNamed:@"someImage1.png"];
UIImage *image2 = [UIImage imageNamed:@"someImage2.png"];

self.imageView.image = image1;
[self.view addSubview:self.imageView];

CABasicAnimation *crossFade = [CABasicAnimation animationWithKeyPath:@"contents"];
crossFade.duration = 5.0;
self.imageView.layer.contents = image2;
[self.imageView.layer addAnimation:crossFade forKey:@"animateContents"];

Did I get a detail wrong or is this not possible.

Update: the above code produces a blank UIImageView. When I change this line:

self.imageView.layer.contents = image2.CGImage;

...I can see the image now but it does not fade in, it just appears instantly.

A: 

My suggestion would be to just use two UIImageViews on top of each other. The one on top has the image1, and on bottom is image2:

- (void) crossfade {
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:.5];
    imageView1.alpha = !imageView1.alpha;
    [UIView commitAnimations];
}

That will fade between the two images whenever you call it. If you want to just do a single fade and remove the first image after you're done:

- (void) crossfade {
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:.5];
    [UIView setAnimationDelegate:imageView1];
    [UIView setAnimationDidStopSelector:@selector(removeFromSuperview)];
    imageView1.alpha = 0
    [UIView commitAnimations];
}

Edit:

If you're looking for a reason why your code doesn't work, it's because you're just setting the property to the new image, then adding a useless animation. CABasicAnimation has the fromValue and toValue that need to be set, then add that animation to the layer, and it should do the animation. Don't set the contents manually.

Ed Marty
You're answer is appreciated but I'm trying to learn about CA animatable properties and the syntax of using key paths rather than how to cross fade images per se. Do you know what I'm doing wrong in my code sample?
willc2
+8  A: 

You were almost there.

CABasicAnimation *crossFade = [CABasicAnimation animationWithKeyPath:@"contents"];
crossFade.duration = 5.0;
crossFade.fromValue = image1.CGImage;
crossFade.toValue = image2.CGImage;
[self.imageView.layer addAnimation:crossFade forKey:@"animateContents"];

Note that the animation is independent of the actual values/contents of the UIImageView. Therefore you'll need to

self.imageView.image = image2;

... to set the final result for your image.

Glen Low
It works, crossfading the image. How do you suppress the compiler warning "Passing argument 1 of 'setFromValue:' from incompatible pointer type"
willc2
.fromValue and .toValue expect a pointer to an Objective-C object, not a pointer to a CFType like CGImageRef is. Therefore you can do this: crossFade.fromValue = (id)(image1.CGImage); crossFade.toValue = (id)(image2.CGImage);
Glen Low