如何防止 macOS 自动将 NSVisualEffectView 插入 NSScrollView

How to prevent macOS from inserting an NSVisualEffectView into an NSScrollView automatically

我通过将 NSStackView 放入 NSScroller 以编程方式构建 NSView 层次结构。我以前做过,我的代码是正确的。

视图层次结构是我所期望的,直到第一次通过运行循环(或显示)时,macOS Catalina(我认为是 Mojave)会自动将 NSVisualEffectView 插入视图层次结构。这把我的自定义绘图搞得一团糟..

我创建的层次结构是

NSScrollView -> NSStackView -> stack subviews

这是"enriched"由第一个显示循环之前的滚动视图进入:

NSScrollView -> NSClipView -> NSStackView -> stack subviews

并且在第一次显示之后,NSVisualEffects 视图被添加到与 NSClipView 相同的级别:

NSScrollView -> NSClipView          -> NSStackView -> stack subviews
             -> NSVisualEffectsView

有没有办法告诉滚动视图我不想要视觉效果视图?

如有任何帮助,我们将不胜感激!

很确定您必须将 drawsBackground 设置为 false。因此,对于 NSScrollView 的引用,您可以在视图加载后调用类似的东西,或者在 xib/storyboard 文件中分配此值。

scrollView.drawsBackground = false

我在尝试重新创建聚光灯时遇到了同样的问题 window。下面的屏幕截图显示了视觉效果视图中的 table 视图(包含在滚动视图中):

在旧版本的macOS中,这里的不透明背景是在滚动视图(或剪辑视图)上绘制的背景,我们可以通过设置清晰的背景颜色或将drawBackground设置为[来简单地删除它。 =13=] 正如卢卡斯所建议的那样。

但是,由于在较新版本的 macOS(也许是 Catalina?)中插入了这个视觉效果视图,这将不起作用:

它的内容背景不透明 material,我找不到任何与此行为相关的 API 或文档。


解决方法

对我有用的是在我的 NSScrollView 子类中隐藏插入的视觉效果视图:

class ScrollView: NSScrollView {
    override func didAddSubview(_ subview: NSView) {
        super.didAddSubview(subview)

        if subview is NSVisualEffectView {
            subview.isHidden = true
        }
    }
}


更新

如果您正在使用 NSTableView,而不是上面的“hack”,最好将 table 视图的样式设置为源列表:

// for macOS 11 Big Sur
tableView.style = .sourceList

// for macOS 10.15 Catalina and older
tableView.selectionHighlightStyle = .sourceList

当您这样做时,系统会自动配置滚动视图和 table 源列表外观(或边栏)视图。更具体地说,滚动视图不插入视觉效果视图,table视图的行视图是semi-transparent。

当您在 NSScrollView 中添加 NSTableViewNSCollectionView 时,其 drawsBackground 属性 将被忽略并添加 NSVisualEffects 视图,除非您在 table 视图和里面的集合视图上明确设置了 .backgroundColor = .clear

所以为了正确的行为:

tableView.backgroundColor = .clear
scrollView.drawsBackground = false