问题描述
我有一个基本的Mac应用程序,该应用程序具有通过自动版式完成的视图动画:
I have a basic Mac app with a view animation done through Auto Layout:
- 我在当前视图的右侧添加一个新视图
- 我更新了约束,以便新视图最终填满窗口
→动画将使该动画看起来像该视图从右侧滑入.
→ The animation will make it appear as if the view slides in from the right.
动画自动版式更改的推荐方法是:
The recommended way for animating Auto Layout changes is:
- 更新约束
- 使用
NSAnimationContext.runAnimationGroup()
- 在动画块内将
allowsImplicitAnimation
设置为true
- 在动画块内调用
view.layoutSubtreeIfNeeded()
- Update the constraints
- Use
NSAnimationContext.runAnimationGroup()
- Set
allowsImplicitAnimation
totrue
inside the animation block - Call
view.layoutSubtreeIfNeeded()
inside the animation block
我遵循了此建议,并且在macOS Sierra上一切正常,但是在macOS High Sierra上,动画不再发生.取而代之的是,视图在没有动画的情况下显示在其最终位置.
I followed this recommendation and everything worked fine on macOS Sierra, but on macOS High Sierra, the animation does not take place anymore. Instead the view shows up at its final position without the animation.
我找到了一种解决方法:我使用DispatchQueue.main.async
将动画安排在下一个运行循环周期中.但是,这似乎是一种黑客行为,我想知道这里是否还有其他遗漏之处.
I found a workaround: I schedule the animation on the next runloop cycle using DispatchQueue.main.async
. However, that seems like a hack and I'm wondering if there is something else I'm missing here.
这是我的实际代码:
private func appendSlideViewControllerAnimated(_ viewController:NSViewController, to viewToTheLeft:NSView)
{
// Insert the new view on the very right, just outside the parent:
viewController.view.frame = self.view.bounds
viewController.view.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(viewController.view)
viewController.view.topAnchor.constraint( equalTo: view.topAnchor ).isActive = true
viewController.view.bottomAnchor.constraint( equalTo: view.bottomAnchor ).isActive = true
viewController.view.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
viewController.view.leadingAnchor.constraint(equalTo: viewToTheLeft.trailingAnchor).isActive = true
// Update the layout after we just added the view on the right:
view.layoutSubtreeIfNeeded()
// Starting with macOS High Sierra, animating constraint changes for the newly inserted view
// only works if scheduled on the next runloop:
//DispatchQueue.main.async {
// Update the constraints to pin the view to the left:
self.view.removeConstraint(self.activeSlideLeadingConstraint!)
self.activeSlideLeadingConstraint = viewController.view.leadingAnchor.constraint(equalTo: self.view.leadingAnchor)
self.activeSlideLeadingConstraint?.constant = 0
self.activeSlideLeadingConstraint?.isActive = true
NSAnimationContext.runAnimationGroup( { context in
self.isAnimating = true
context.duration = self.slidingAnimationDuration
context.allowsImplicitAnimation = true
self.view.layoutSubtreeIfNeeded()
}, completionHandler: {
viewToTheLeft.removeFromSuperview()
self.clearUndoHistory()
self.updateFirstResponder()
self.isAnimating = false
})
//}
}
推荐答案
为要设置动画的根视图启用Core Animation支持.可以在Interface Builder中完成,也可以通过编程方式完成:
Enable Core Animation backing for root view you trying to animate. It can be done in Interface Builder or programmatically:
override func viewDidLoad()
{
super.viewDidLoad()
view.wantsLayer = true
}
这篇关于使用NSView.layoutSubtreeIfNeeded()对自动布局约束进行动画处理在macOS High Sierra上不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!