【问题标题】:Are layer-backed NSView siblings allowed to overlap?支持层的 NSView 兄弟姐妹是否允许重叠?
【发布时间】:2012-05-30 00:12:04
【问题描述】:

我有点困惑。 Apple Documentation 声明如下:

注意:出于性能原因,Cocoa 不强制在 同级视图或保证正确的失效和绘图行为 当兄弟视图重叠时。如果你想在前面绘制一个视图 另一个视图,您应该将前视图设置为子视图(或后代) 后视图。

因此根据这一点,兄弟视图不应重叠,否则行为未定义。

然而,在Cocoa Slides demo app 中,支持层的 NSView 兄弟确实重叠,它似乎工作得很好:

那么 Cocoa Slides 示例代码是错误的,它的工作原理只是巧合,还是文档已过时?自 10.5 以来已过时,是吗?

【问题讨论】:

    标签: cocoa core-animation calayer nsview


    【解决方案1】:

    在 Leopard 及更高版本上,无论是否支持图层,重叠视图都可以正常工作。

    【讨论】:

    • 我对这个话题的观察与@uliwitness 的回答相符。当您混合和匹配 layer-backed 和 non-layer-backed 视图时有一些注意事项。
    • 不幸的是,如果它们没有分层,它们就不起作用。我尝试借助一个额外的 NSView 在 CEF(铬嵌入式框架)窗口中打一个洞,因此它不会在它之后呈现。 (似乎 CEF 在内部使用 OpenGL 或其他魔法)。我发现的唯一方法是让我的 NSView 分层并让 CEF 保持正常
    • Uli,这是引文:)
    【解决方案2】:

    经过一番研究,Apple 文档似乎确实已经过时了。

    自 10.5 起,支持层的 NSView 同级允许重叠。

    这个discussion from 2009,涉及苹果工程师大卫邓肯和Corbin Dunn,终于给出了一些明确的答案:

    重叠视图在 Leopard 上有效,但在此之前无效。这 文档已过期。

    我有一组视图,每个视图内部都有许多较小的视图, 需要以重叠的方式呈现在相同的 把它们放在窗户上,这样它们就可以互相看到了。在我的 初步测试,我把每个大视图都变成了单个的兄弟 背景视图。本来打算把每一个都带上前线, 必要时通过重新排列 z 顺序。有没有未来(或 存在)在这种方法中?

    这将适用于 Leopard。

    来源:http://www.cocoabuilder.com/archive/cocoa/228191-nsview-behaves-different-on-10-4-vs-10-5.html#228983

    更新:James Dempsey also replied on Twitter:

    我的理解是,从 10.5 开始,重叠的兄弟视图都可以,无论是否支持图层。

    【讨论】:

    • 非层支持的 NSView 兄弟不允许重叠。看我的回答。
    • @nschmidt 有趣。您是否可能有一个示例应用程序表明具有非层支持的重叠同级 NSView 是有问题的?两名(前)Apple 工程师表示,从 10.5 开始就很好,在我的测试中,这似乎是真的。
    • 我已经上传了一个简单的演示到github。背景中有一个滚动视图,与几个视图重叠。当你滚动时,一切都搞砸了。
    • @nschmidt 太好了,谢谢。根据我的经验 NSScrollView 似乎是它自己的野兽。 NSScrollView 有一个完整的内部视图层次结构,当它们没有层支持时,它确实不能很好地与重叠的兄弟视图一起使用。不过,其他不那么复杂的视图重叠得很好。
    【解决方案3】:

    支持层的视图由 OpenGL 分层(嗯,Quartz 合成器,但将每个层视为一个带有 OpenGL 纹理的多边形会有所帮助),因此它们始终支持正确的重叠。

    CocoaBuilder/Cocoa-Dev 上的帖子根本没有提到层。这意味着它谈论的是没有支持 CALayer 的常规 NSView(或者更确切地说,整个窗口只有一个 CALayer)。

    提到的一个例外是 OpenGLView(同样,没有图层),它总是在窗口顶部合成它的 OpenGL 矩形,消除任何子视图。我不认为让 NSOpenGLView 层支持工作,但可以使用 OpenGL 层代替,它将在其他层之间正确合成。

    另一个例外是非 layer-backed 视图之上的层,这是有道理的,因为所有非 layer-backed 视图都有效地驻留在单个层中,该层当然位于其任何子层之下(该层-必须是托管在非层支持的父视图中的支持视图)。

    简而言之,它从 10.5 开始适用于非分层视图,并且永远适用于支持层的视图,但在混搭或使用 OpenGL 时需要注意。

    PS - 不过,我不能 100% 肯定关于重叠非层支持视图的声明应该被视为规范。这是苹果工程师的非正式声明。事情可能已经改变,并且可能已经发现了使事情无法正常工作的错误。当我想要正确重叠时,我通常会使用图层。

    【讨论】:

    • 有趣!我什至没有注意到他们没有明确提到层。然而,Core Animation 是从 10.5 开始才出现的,所以在此之前没有图层支持的视图。您确定重叠在非层支持的视图中可靠地工作吗?这是我第一次听说(不过会很棒!)。这也可能是相关的:stackoverflow.com/questions/466297/…
    • 我没有说在任何地方重叠都适用于非层支持的视图。它确实不在旧版本中工作(虽然它通常看起来有效,但在随机情况下它会中断,重叠的非层支持的视图有一些非常不确定的东西)
    • 哦,看来我确实说过它“从 10.5 开始适用于非分层”。 :-S
    【解决方案4】:

    这可能对某人有用:我在 MacOS 10.7+ 上遇到了闪烁重叠的非分层子视图的问题。在我的应用程序中,视图用于呈现有关选定图形对象(选择框、缩放控制点等)的一些信息,因此它们具有一些 动画 - 这对我来说是关键。

    似乎重叠的兄弟姐妹即使没有图层也能正常工作,但在更简单的情况下。我有一堆动画视图,每个视图都有自己的计时器 - 它轻弹。我找到了两种解决方案:打开layers或同步动画,切换到单个共享计时器并同时更新所有视图。

    至少这个技巧对我的应用有所帮助,因为我不想使用图层。

    【讨论】:

    • 没错,如果您正在为同级 NSView(与另一个 NSView 重叠)设置动画,那么您会看到闪烁和奇怪的行为。如果您希望它看起来正确,则需要在动画期间更新所有视图。
    【解决方案5】:

    NSView 兄弟通常允许重叠。不过,您可能会遇到的一件事是 NSScrollView 默认是如何工作的。当您有一个与兄弟视图重叠的 vanilla NSScrollView 时,事情就会中断。

    这是因为 NSClipView 仅绘制视图中滚动的部分并复制未更改的内容。当您有与滚动视图重叠的同级视图时,此优化不起作用,并且即使它们只是同级视图,视图似乎也会滚动。

    要使重叠的同级视图即使在没有层支持的情况下也能正常工作,您必须禁用此优化:

    [scrollView.contentView setCopiesOnScroll:NO];
    

    【讨论】:

      猜你喜欢
      • 2013-02-04
      • 1970-01-01
      • 2017-08-18
      • 2019-05-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-14
      相关资源
      最近更新 更多