Alexsander Akers
Alexsander Akers

Reputation: 16024

How can I animate a content switch in an NSImageView?

I want to switch the image shown in an NSImageView, but I want to animate that change. I've tried various methods to do this. Hopefully one of you could suggest one that might actually work. I'm working with Cocoa for Mac.

Upvotes: 7

Views: 4535

Answers (2)

Nicholas Riley
Nicholas Riley

Reputation: 44331

As far as I know, NSImageView doesn't support animating image changes. However, you can place a second NSImageView on top of the first one and animate hiding the old one and showing the new one. For example:

NSImageView *newImageView = [[NSImageView alloc] initWithFrame: [imageView frame]];
[newImageView setImageFrameStyle: [imageView imageFrameStyle]];
// anything else you need to copy properties from the old image view
// ...or unarchive it from a nib

[newImageView setImage: [NSImage imageNamed: @"NSAdvanced"]];
[[imageView superview] addSubview: newImageView
                       positioned: NSWindowAbove relativeTo: imageView];
[newImageView release];

NSDictionary *fadeIn = [NSDictionary dictionaryWithObjectsAndKeys:
             newImageView, NSViewAnimationTargetKey,
             NSViewAnimationFadeInEffect, NSViewAnimationEffectKey,
             nil];
NSDictionary *fadeOut = [NSDictionary dictionaryWithObjectsAndKeys:
             imageView, NSViewAnimationTargetKey,
             NSViewAnimationFadeOutEffect, NSViewAnimationEffectKey,
             nil];
NSViewAnimation *animation = [[NSViewAnimation alloc] initWithViewAnimations:
              [NSArray arrayWithObjects: fadeOut, fadeIn, nil]];
[animation setAnimationBlockingMode: NSAnimationBlocking];
[animation setDuration: 2.0];
[animation setAnimationCurve: NSAnimationEaseInOut];
[animation startAnimation];
[imageView removeFromSuperview];
imageView = newImageView;
[animation release];

If your view is big and you can require 10.5+, then you could do the same thing with Core Animation, which will be hardware accelerated and use a lot less CPU.

After creating newImageView, do something like:

[newImageView setAlphaValue: 0];
[newImageView setWantsLayer: YES];
// ...
[self performSelector: @selector(animateNewImageView:) withObject: newImageView afterDelay: 0];

- (void)animateNewImageView:(NSImageView *)newImageView;
{
    [NSAnimationContext beginGrouping];
    [[NSAnimationContext currentContext] setDuration: 2];
    [[newImageView animator] setAlphaValue: 1];
    [[imageView animator] setAlphaValue: 0];
    [NSAnimationContext endGrouping];
}

You'll need to modify the above to be abortable, but I'm not going to write all your code for you :-)

Upvotes: 7

Rob Keniger
Rob Keniger

Reputation: 46020

You could implement your own custom view that uses a Core Animation CALayer to store the image. When you set the contents property of the layer, the image will automatically smoothly animate from the old image to the new one.

Upvotes: 5

Related Questions