cocoa - 使用核心动画的 NSView 显式动画

标签 cocoa delegates core-animation nsview explicit

我正在尝试使用核心动画在 NSView 中滑动。我认为我需要使用显式动画,而不是依赖于诸如 [[view animator] setFrame:newFrame] 之类的东西。这主要是因为我需要设置动画委托(delegate)以便在动画完成后采取行动。

我使用动画师让它工作得很好,但正如我所说,动画完成时我需要收到通知。我的代码目前如下所示:

// 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"];

这在视觉上是有效的(我在最后得到通知),但看起来实际的 controlView 没有移动。如果我刷新窗口,controlView 就会消失。我尝试更换

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

[controlView setFrame:newFrame];

这确实会导致 View (和图层)移动,但它会破坏某些东西,导致我的应用程序很快就会因段错误而终止。

大多数显式动画的示例似乎只是移动 CALayer。必须有一种方法可以移动 NSView 并且能够设置委托(delegate)。任何帮助将不胜感激。

最佳答案

对 View 所做的更改在当前运行循环结束时生效。这同样适用于应用于图层的任何动画。

如果您对 View 的图层进行动画处理, View 本身不会受到影响,这就是动画完成时 View 似乎跳回其原始位置的原因。

考虑到这两点,您可以通过将 View 的框架设置为动画完成时您想要的效果,然后向 View 的图层添加显式动画来获得您想要的效果。

当动画开始时,它将 View 移动到起始位置,将其动画到结束位置,当动画完成时, View 将具有您指定的帧。

- (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"];
}

当然,要使此代码正常工作,您需要确保您的 View 及其父 View 都有图层。如果 super View 没有图层,您将得到损坏的图形。

关于cocoa - 使用核心动画的 NSView 显式动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6064221/

相关文章:

ios - 未调用第二个 ViewController 中的委托(delegate)方法

function - D (dlang) 将 lambda 函数作为参数传递

ios - 核心动画 setFromValue

iOS - 核心动画 - View 在意外时发生变化

macos - 在 Cocoa 中强制低分辨率?

iphone - 如何管理静态、延迟加载的字典和数组的内存负载

iphone - 当应用程序已经运行时将本地通知声音静音

objective-c - NSArrayController + NSTableView : automatically save changes without Core Data

iphone - 检测何时推送 Viewcontroller

cocoa-touch - UITableViewCell 子类,在代码中绘制,动画中的删除按钮