NSSplitViewItem折叠动画和窗口setFrame冲突

时间:2014-07-05 10:04:14

标签: multithreading core-animation swift nssplitview

我试图在移动其包含的窗口的同时制作一个(新的10.10)NSSplitViewItem折叠和展开,以便保持整个事物"到位"。

问题是我在动画中出现了抽搐(如here所示)。

我正在进行折叠的代码是:

func togglePanel(panelID: Int) {

     if let splitViewItem = self.splitViewItems[panelID] as? NSSplitViewItem {

          // Toggle the collapsed state
          NSAnimationContext.runAnimationGroup({ context in

               // special case for the left panel
               if panelID == 0 {
                    var windowFrame = self.view.window.frame
                    let panelWidth = splitViewItem.viewController.view.frame.width
                    if splitViewItem.collapsed {
                         windowFrame.origin.x -= panelWidth
                         windowFrame.size.width += panelWidth
                    } else {
                         windowFrame.origin.x += panelWidth
                         windowFrame.size.width -= panelWidth
                    }
                    self.view.window.animator().setFrame(windowFrame, display: true)
               }
               splitViewItem.animator().collapsed = !splitViewItem.collapsed
          }, completionHandler: nil)
     }
}

我知道"不要越过溪流"问题(来自会话213,WWDC
 13),其中调整在主线程上运行的动画的窗口和在单独线程上运行的核心动画折叠动画相互干扰。将splitViewItem折叠动画放到主线程上似乎是错误的方法,我感到有一种唠叨的感觉,这是一种更好的方法,我错过了。

由于我没有在任何地方找到NSSplitViewItems的任何文档(还),我将不胜感激任何见解。

如果有人想看一下,我在GitHub here上有一个小测试项目。

更新现在已经使用解决方案更新了上述项目。

谢谢, TEO

2 个答案:

答案 0 :(得分:13)

问题类似于“不要跨越流”问题,因为你创建的动画有两个驱动程序:(1)拆分视图项(2)窗口,它们不是同步。

在'13 Cocoa Animations talk的例子中,设置约束以产生正确的窗内动画,因为只有窗口的帧被动画化。

这里可以尝试类似的东西 - 仅动画窗口的框架而不是分割视图项目,但由于项目管理用于(解除)崩溃的约束,应用程序无法准确控制窗口内部内容的动画效果:

Animating Window frame

相反,拆分视图项动画可以完全驱动动画并使用NSWindow的-anchorAttributeForOrientation:来描述窗口框架的影响。

if let splitViewItem = self.splitViewItems[panelID] as? NSSplitViewItem {
    let window = self.view.window
    if panelID == 0 {
        // The Trailing edge of the window is "anchored", alternatively it could be the Right edge
        window.setAnchorAttribute(.Trailing, forOrientation:.Horizontal)
    }
    splitViewItem.animator().collapsed = !splitViewItem.collapsed
}

Animating SplitViewItem

答案 1 :(得分:2)

对于使用Objective C并定位10.11 El Capitan的任何人。 这对我来说很成功,不需要设置AnchorAttributes。

splitViewItem.collapsed = YES;