Explicit animation of NSView using basic animation

I am trying to NSView in an NSView using the main animation. I think I need to use explicit animation, and not rely on something like [[view animator] setFrame:newFrame] . This is mainly because I need to set an animation delegate to take action after the animation finishes.

It works fine for me, using the animator, but, as I said, I need to get a notification when the animation ends. Currently my code is as follows:

 // Animate the controlView NSRect viewRect = [controlView frame]; NSPoint startingPoint = viewRect.origin; NSPoint endingPoint = startingPoint; endingPoint.x += viewRect.size.width; [[controlView layer] setPosition:NSPointToCGPoint(endingPoint)]; CABasicAnimation *controlPosAnim = [CABasicAnimation animationWithKeyPath:@"position"]; [controlPosAnim setFromValue:[NSValue valueWithPoint:startingPoint]]; [controlPosAnim setToValue:[NSValue valueWithPoint:endingPoint]]; [controlPosAnim setDelegate:self]; [[controlView layer] addAnimation:controlPosAnim forKey:@"controlViewPosition"]; 

This works visually (and I get a notification at the end), but it looks like the actual control is not moving. If I make the window refresh, the View control will disappear. I tried to replace

 [[controlView layer] setPosition:NSPointToCGPoint(endingPoint)]; 

from

 [controlView setFrame:newFrame]; 

and this causes the view (and layer) to move, but it distorts something so that my application will soon fail with a seg error.

Most examples of explicit animations seem to move only CALayer . There must be a way to move the NSView , as well as the ability to set a delegate. Any help would be appreciated.

+7
source share
2 answers

I think you need to call setPosition at the end (after setting the animation). In addition, I do not think that you should animate the presentation layer explicitly, but instead the view itself using the animator and setting the animation. You can also use delegates with animator :)

 // create controlPosAnim [controlView setAnimations:[NSDictionary dictionaryWithObjectsAndKeys:controlPosAnim, @"frameOrigin", nil]]; [[controlView animator] setFrame:newFrame]; 
+5
source

Changes to views take effect at the end of the current run cycle. The same goes for any animations applied to layers.

If you animate a view layer, the view itself is not affected, so the view seems to return to its original position after the animation is complete.

With these two things in mind, you can get the desired effect by setting the presentation frame to what you want when the animation is done, and then add explicit animation to the presentation level.

When the animation begins, it moves the view to its original position, animates it to its final position, and when the animation is complete, the view has the frame you specify.

 - (IBAction)animateTheView:(id)sender { // Calculate start and end points. NSPoint startPoint = theView.frame.origin; NSPoint endPoint = <Some other point>; // We can set the frame here because the changes we make aren't actually // visible until this pass through the run loop is done. // Furthermore, this change to the view frame won't be visible until // after the animation below is finished. NSRect frame = theView.frame; frame.origin = endPoint; theView.frame = frame; // Add explicit animation from start point to end point. // Again, the animation doesn't start immediately. It starts when this // pass through the run loop is done. CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"]; [animation setFromValue:[NSValue valueWithPoint:startPoint]]; [animation setToValue:[NSValue valueWithPoint:endPoint]]; // Set any other properties you want, such as the delegate. [theView.layer addAnimation:animation forKey:@"position"]; } 

Of course, in order for this code to work, you need to make sure that your view and its supervisor have layers. If the supervisor does not have a layer, you will get corrupted graphics.

+8
source

All Articles