Update: My original post was about how to animate two rects on an iPhone but that was not what the original poster/question asked. That's what I get for trying to answer SO questions after 24 hours of coding. Anyhoo, I'm going to leave that answer here in case anyone comes along and wants to learn about this on the iPhone. Here is an example to do the exact same thing on a Mac. Note that this example expects you to first setup a sample project in Interface Builder with an NSWindow (any default project should do that):
------ Mac Example:
// MacAnimationExample.h:
#import <Cocoa/Cocoa.h>
#import <QuartzCore/QuartzCore.h>
@interface ColorView : NSView {
NSColor *backgroundColor;
}
@property( nonatomic, retain ) NSColor *backgroundColor;
@end
@interface MacAnimationExample : NSObject <NSAnimationDelegate, NSApplicationDelegate> {
ColorView *red;
ColorView *yellow;
IBOutlet NSWindow *window;
}
@property( assign ) IBOutlet NSWindow *window;
@end
// MacAnimationExample.m:
#import "MacAnimationExample.h"
@implementation ColorView
@synthesize backgroundColor;
- (void) setBackgroundColor:(NSColor *) iColor {
[iColor retain];
[backgroundColor release];
backgroundColor = iColor;
[self setNeedsDisplay: YES];
}
- (void) drawRect:(NSRect) iRect {
[backgroundColor set];
NSRectFill( iRect );
}
@end
@implementation MacAnimationExample
@synthesize window;
- (void) animateIt {
NSAnimation *animation;
NSArray *animations;
NSRect redFrame, yellowFrame;
NSMutableDictionary *redInfo, *yellowInfo;
redFrame = [red frame];
yellowFrame = [yellow frame];
redInfo = [NSMutableDictionary dictionary];
[redInfo setObject: red forKey: NSViewAnimationTargetKey];
[redInfo setObject: [NSValue valueWithRect: redFrame] forKey: NSViewAnimationStartFrameKey];
[redInfo setObject: [NSValue valueWithRect: yellowFrame] forKey: NSViewAnimationEndFrameKey];
yellowInfo = [NSMutableDictionary dictionary];
[yellowInfo setObject: yellow forKey: NSViewAnimationTargetKey];
[yellowInfo setObject: [NSValue valueWithRect: yellowFrame] forKey: NSViewAnimationStartFrameKey];
[yellowInfo setObject: [NSValue valueWithRect: redFrame] forKey: NSViewAnimationEndFrameKey];
animations = [NSArray arrayWithObjects: redInfo, yellowInfo, nil];
animation = [[[NSViewAnimation alloc] initWithViewAnimations: animations] autorelease];
[animation setDelegate: self];
[animation setDuration: 0.5];
[animation startAnimation];
}
- (void) animationDidEnd:(NSAnimation*) animation {
[self animateIt];
}
- (void) applicationDidFinishLaunching:(NSNotification *) aNotification {
NSRect bounds;
NSView *contentView;
contentView = [window contentView];
bounds = [contentView bounds];
bounds.size.width = floorf( bounds.size.width * 0.5 );
red = [[[ColorView alloc] initWithFrame: bounds] autorelease];
red.backgroundColor = [NSColor redColor];
[contentView addSubview: red];
bounds.origin.x += bounds.size.width;
yellow = [[[ColorView alloc] initWithFrame: bounds] autorelease];
yellow.backgroundColor = [NSColor yellowColor];
[contentView addSubview: yellow];
[self animateIt];
}
@end
------ iPhone Example:
Here's an example that shows how to animate two rects. Once you get this figured out the rest of the simple UIView-based animation is pretty easy. There is lower layer CoreAnimation stuff you can look into and with newer OS's there's an animation block concept that you can look at. This is where you should start though:
@interface ExampleViewController : UIViewController {
UIView *red;
UIView *yellow;
}
@end
@implementation ExampleViewController
- (void) loadView {
UIView *background;
CGRect frame;
frame = [UIScreen mainScreen].bounds;
// background view contains red & yellow subviews
background = [[[UIView alloc] initWithFrame: frame] autorelease];
frame.size.width = floorf( frame.size.width * 0.5 );
red = [[[UIView alloc] initWithFrame: frame] autorelease];
red.backgroundColor = [UIColor redColor];
frame.origin.x = frame.size.width;
yellow = [[[UIView alloc] initWithFrame: frame] autorelease];
yellow.backgroundColor = [UIColor yellowColor];
[background addSubview: yellow];
[background addSubview: red];
self.view = background;
}
- (void) viewWillAppear:(BOOL) animated {
CGRect temp;
// normally you will let the animated parameter
// control whether or not the view animates. for
// demonstation I add a hack to force animation to begin:
animated = YES; // hack
if ( animated ) {
[UIView beginAnimations: nil context: nil];
[UIView setAnimationDelegate: self];
[UIView setAnimationDidStopSelector: @selector(startAnimation)];
[UIView setAnimationDuration: 0.5];
}
temp = red.frame;
red.frame = yellow.frame;
yellow.frame = temp;
if ( animated ) [UIView commitAnimations];
}
- (void) startAnimation {
[self viewWillAppear: YES];
}
@end