如何缓存图层内容并在调整大小/动画期间使用它?

问题描述:

我注意到,在macOS的Finder中,当边栏合拢/展开时,图标和文本被压缩或拉伸(请参见下面的截图)。我想这是一个优化,防止在动画过程中重新绘制图层。如何缓存图层内容并在调整大小/动画期间使用它?

我试图编写一个模仿该行为的自定义NSTableCellView子类。但我不知道从哪里开始,具体如下:

  1. 如何在动画启动时得到通知,以便我可以设置图层的内容。
  2. 如何在动画完成时重新绘制视图或图层,以免它再次使用缓存的内容。

我从下面的脚手架代码开始。 (该draw(_ dirtyRect: NSRect)方法将不被调用时wantsUpdateLayer返回true。这可以根据this doc是优化)

 class TableCellView: NSTableCellView { 

     override func draw(_ dirtyRect: NSRect) { 
      print(#file, #line, "draw tcell view") 
      super.draw(dirtyRect) 

      // Drawing code here. 
     } 

     override var wantsUpdateLayer: Bool { 
      print(#file, #line, "want") 
      return true 
     } 

     override func updateLayer() { 
      print(#file, #line, "update") 
      super.updateLayer() 
     } 

    } 

enter image description here

如果视图使用一个层作为它的后备存储器(wantsLayer = true),则可以设置视图的layerContentsRedrawPolicy执行这些相同的优化。默认情况下(如果了AppKit创建的层),该内容将被连续动画大小调整期间重绘到视图的背衬层:

对于层支持的视图 - 即,用于该了AppKit创建的层的视图 - AppKit默认将内容重绘策略设置为duringViewResize

例如,通过将策略设置为beforeViewResize,视图将在调整大小动画开始时重绘一次。

NSView.LayerContentsRedrawPolicy列出了所有可能的重绘策略。

+0

谢谢。我的观点是分层支持的。我已经注意到这个'layerContentsRedrawPolicy'并试图将它设置为'.beforeViewResize'和'crossfade'。它在Sierra上无效。我的另一台机器已经升级到高级Sierra,我在那台机器上发现了**,它在层次结构中更高的另一个视图上有效,但我没有用'NSTableCellView'尝试它。在塞拉利昂它没有效果。我离开了我的High Sierra机器,所以我只能在本周对Sierra进行编码。 – LShi