使用核心动画显式动画NSView

bts*_*umy 7 cocoa delegates core-animation explicit nsview

我正在尝试NSView使用核心动画进行滑动.我想我需要使用显式动画而不是依赖于类似的东西[[view animator] setFrame:newFrame].这主要是因为我需要设置动画委托才能在动画结束后采取行动.

我使用动画师工作得很好,但正如我所说,我需要在动画结束时收到通知.我的代码目前看起来像:

// 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"];
Run Code Online (Sandbox Code Playgroud)

这在视觉上有效(并且我在最后得到通知),但看起来实际的controlView没有被移动.如果我使窗口刷新,controlView将消失.我试过更换

[[controlView layer] setPosition:NSPointToCGPoint(endingPoint)];
Run Code Online (Sandbox Code Playgroud)

[controlView setFrame:newFrame];
Run Code Online (Sandbox Code Playgroud)

这确实会导致视图(和图层)移动,但它会破坏某些东西,以至于我的应用程序很快就会因为seg故障而死亡.

大多数显式动画的例子似乎只是在移动a CALayer.必须有一种方法来移动NSView并且还能够设置代理.任何帮助,将不胜感激.

Col*_*lin 8

对视图所做的更改将在当前运行循环结束时生效.对于应用于图层的任何动画也是如此.

如果为视图的图层设置动画,则视图本身不受影响,这就是为什么视图在动画完成时会跳回到原始位置的原因.

考虑到这两点,您可以通过将视图的帧设置为动画完成时的所需效果,然后向视图的图层添加显式动画,来获得所需的效果.

动画开始时,它会将视图移动到起始位置,将其动画到结束位置,动画完成后,视图会显示您指定的帧.

- (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's 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"];
}
Run Code Online (Sandbox Code Playgroud)

当然,要使此代码正常工作,您需要确保视图及其超级视图都具有图层.如果超级视图没有图层,则会损坏图形.


Mic*_*lar 5

我认为你需要在结束时调用setPosition(在设置动画之后).另外,我认为你不应该明确地为视图层设置动画,而是通过使用动画设置动画来设置视图.您也可以使用animator :)代表

// create controlPosAnim
[controlView setAnimations:[NSDictionary dictionaryWithObjectsAndKeys:controlPosAnim, @"frameOrigin", nil]];
[[controlView animator] setFrame:newFrame];
Run Code Online (Sandbox Code Playgroud)