Reputation:
I have an animation which moves some views around. When this animation completes I want the window to recalculate the keyview loop. My code is simmilar to the follow mock code:
[NSAnimationContext beginGrouping];
[newView setAlpha: 0.0]; //hide newView
[self addSubView:newView];
//position the views
[[oldView animator] setFrame: newFrame1];
[[newView animator] setFrame: newFrame2];
[[newView animator] setAlpha: 1.0]; //fade-in newView
[NSAnimationContext endGrouping];
[[self window] recalculateKeyViewLoop];
The problem with this code is that recalculateKeyViewLoop
is called before the views are in their new positions which means that the keyviewloop is wrong.
How do I fix this?
My first though is to call recalculateKeyViewLoop
in a callback from when the animation ends but I can't figure out how to do this.
Upvotes: 4
Views: 3595
Reputation: 1989
You can use a completion handler like this:
[NSAnimationContext runAnimationGroup:^(NSAnimationContext *context){
// Start some animations.
[[myView animator] setFrameSize:newViewSize];
[[myWindow animator] setFrame:newWindowFrame display:YES];
} completionHandler:^{
// This block will be invoked when all of the animations started above have completed or been cancelled.
NSLog(@"All done!");
}];
Upvotes: 1
Reputation: 16317
If you are animating an NSWindow
(as opposed to an NSView
), the other answers will not work and you should do this instead:
CAAnimation *animation = [CABasicAnimation animation];
animation.delegate = self;
self.window.animations = @{@"frame": animation};
[[self.window animator] setFrame:NSMakeRect(0, 0, 400, 200) display:YES];
which will then call the animationDidStop:finished:
method on your delegate (which in the above code would be self
)
Upvotes: 0
Reputation: 1603
Check out my post here: How would I do this iOS animation on OSX?
I wrote a class that handles this for you, using blocks. Hopefully your target allows blocks! :)
Upvotes: 0
Reputation: 8823
Something that's not so obvious, or at least wasn't to me, is that there are two animations going on when you do a setFrame:
, with keys frameSize
and frameOrigin
.
Depending on what your original and final frames are you may need to register yourself as a delegate for one or both of them.
I'd also recommend that you make a copy of the animation you get back from -animationForKey:
and store your modified copy in the animations
dictionary of your object. This way your delegate will only be called at the conclusion of that particular objects' animator duration, versus all objects animating that key.
eg.
CAAnimation *animation = [[view animationForKey:@"frameOrigin"] copy];
animation.delegate = self;
[view setAnimations:[NSDictionary dictionaryWithObject:animation forKey:@"frameOrigin"]];
In this way your animation object will supersede the default animation object for that view. Then implement whichever delegate methods you're interested in.
Upvotes: 5
Reputation: 96333
You should be able to send -animationForKey:
to your views to get a CAAnimation
instance, then set yourself as its delegate and implement the method that Adam mentioned.
Upvotes: 4
Reputation: 22587
if you use CAAnimation this has an animationDidStop:finished: delegate method..
Hope this helps
Upvotes: 1