NSView 上的动画自动布局约束和 Alpha

Animate Auto Layout Constraints and Alpha on NSView

Swift 3, iOS 10, macOS 10.12.4

我正在构建一个在 iOS 和 Mac 上运行的应用程序。在 iOS 方面,我已经成功地制作了 UIView 动画。当用户点击某物时,会出现一个弹出窗口并动画到位。这是我在 tap 事件中的代码:

self.popupConstraintX.constant = x
self.popupConstraintY.constant = y

UIView.animate(withDuration: 0.25 , delay: 0.0, options: .curveLinear, animations: {
  self.graphPopup.alpha = 1.0
  self.layoutIfNeeded()

}, completion:nil)

在这种情况下,self 指的是 UITableViewCell 包含 graphPopup

我在 Mac 端构建了相同的东西,但我正在尝试制作 graphPopup 的动画,它现在是 NSView。这是我目前在 click 事件中的内容:

self.popupConstraintX.constant = x
self.popupConstraintY.constant = y

self.view.layoutSubtreeIfNeeded()

NSAnimationContext.runAnimationGroup({_ in
  self.graphPopup.alphaValue = 1.0
  
  //Indicate the duration of the animation
  NSAnimationContext.current().duration = 0.25
  NSAnimationContext.current().allowsImplicitAnimation = true
  self.view.updateConstraints()
  self.view.layoutSubtreeIfNeeded()
  
}, completionHandler:nil)

这里的self指的是包含NSViewController。没有任何动画——不是 graphPopup 的位置或 alpha。它就像 1985 年在 Atari 上一样出现和消失。

知道我的 NSView 动画有什么问题吗?


更新

为了后代,这里是 BJ 建议的工作代码(稍微调整一下以使用隐式动画上下文):

self.popupConstraintX.constant = x
self.popupConstraintY.constant = y

NSAnimationContext.runAnimationGroup({context in
  context.duration = 0.25
  context.allowsImplicitAnimation = true
  
  self.graphPopup.alphaValue = 1.0
  self.view.layoutSubtreeIfNeeded()
  
}, completionHandler:nil)

alphaValue 的修改发生在您打开隐式动画之前,因此不会对 alpha 进行动画处理。我不清楚这是有意还是无意。

视图未根据 popupConstraint 给定的位置设置动画,因为您实际上并未在动画块内执行任何会导致视图框架发生变化的操作。为了触发隐式动画,您不仅要更新约束;您还必须确保视图的 frame 在动画块内发生变化。如果您使用的是 AutoLayout,这通常是通过调用 layoutSubtreeIfNeeded.

来完成的

但是,因为您更新了约束并在动画块之前调用了 layoutSubtreeIfNeeded(),所以块内没有其他帧更改(除非有updateConstraints() 发生了一些你没有给我们看的事情。)

您应该删除对 layoutSubtreeIfNeeded() 的第一个调用,或者如果仍然需要,将其放在 popupConstraint 修改之上。然后,当您在动画块中调用 layoutSubtreeIfNeeded() 时,将根据这些更改的约束设置一个新帧,您应该会看到动画发生。

Swift 5

animator()是关键。

你可以简单地这样做:

 NSAnimationContext.runAnimationGroup({ context in

    //Indicate the duration of the animation
    context.duration = 0.25
    self.popupConstraintX.animator().constant = x
    self.popupConstraintY.animator().constant = y
    self.graphPopup.animator().alphaValue = 1.0
   
   }, completionHandler:nil)