Sheet 中 NSPredicateEditor 的 macOS 深色模式 UI 错误

macOS Dark Mode UI bugs with NSPredicateEditor in a Sheet

在 Mac 应用程序中,我展示了一个包含 NSPredicateEditor 的 sheet:

parentViewController.presentAsSheet(predicateEditor)

我在此处为此行为创建了一个示例项目:
https://github.com/pkamb/Feedback_NSPredicateEditor

在 macOS 10.14 Mojave 和 10.15 Catalina 中,引入深色模式后,这会导致一些 UI 错误。

NSPredicateEditor 控件的背景与行/父视图的背景不匹配。注意 is 背景和文本字段的背景。

  1. 深色模式:

  1. 灯光模式:

如何修复这些 sheet 出现的 NSPredicateEditor UI 错误?

错误报告:

编辑:

此相同更改已在 Xcode 更新中引入,不再需要。在这里查看答案:


默认情况下,NSPredicateEditor 的祖父视图应该是 NSScrollView:

如果您为该滚动视图提供 clearColor 透明背景,major Dark Mode issue 将大部分得到修复。如果您在光照模式下保持此 alpha 更改处于活动状态,谓词编辑器将采用白色背景而不是默认的灰色视图背景。

As Apple says,在 layout() 中进行此更改,或者在系统外观更改时让您的视图有机会自我更新的其他方法之一。

class NSPredicateEditorDarkModeFix: NSPredicateEditor {

    override func layout() {
        defer { super.layout() }

        guard let clipView = self.superview as? NSClipView, let scrollView = clipView.superview as? NSScrollView else {
            return
        }

        let alpha: CGFloat = NSAppearance.current.name == .darkAqua ? 0.0 : 1.0
        scrollView.backgroundColor = scrollView.backgroundColor.withAlphaComponent(alpha)
    }

}

深色模式 NSPredicateEditor 仍然存在一些 UI 问题,即每个控件的灰色背景框。

这里的 The Omni Show 播客讨论了此修复:

https://theomnishow.omnigroup.com/episode/rey-worthington-omnigraffle-engineer https://twitter.com/theomnishow/status/1052630270719868928

Apple 已回复我的错误报告,并表示以下极其糟糕的暗模式行为已通过最近对 Xcode 的更新得到修复。

您可能仍需要手动修复此处答案中更细微的错误:

Apple 的这个回答只是对此处看到的极其严重的暗模式错误的修复:

NSPredicateEditor presented by a Sheet is completely broken in Dark Mode

rdar://46142171

Apple 开发者关系:

To fix the dark mode appearance, you should reset that scollview background color to default

我:

Are you saying that a fix has been made in an update to Mojave?

The scrollview clearcolor background was needed in order to make the NSPredicateEditor at all workable in Dark Mode.

Apple 开发者关系:

No, in Xcode you need to change the scollview background color to its Default (controlBackgroundColor)

我:

Ok, I'm seeing this behave mostly ok now after switching (back) to the controlBackgroundColor. aka removing my clearColor fix

However, this was definitely NOT working in the past with that color selected. Can you provide any info about when this was fixed in OS X or Xcode?

Apple 开发者关系:

This was fixed in Xcode

此答案修复了 NSPredicate 编辑器控件的细微错误背景颜色,如下所示:

  • 灯光模式:https://i.stack.imgur.com/3E4L4.png
  • 深色模式:https://i.stack.imgur.com/AqbQ5.png

将视觉效果视图 using a flipped coordinate system 插入谓词编辑器视图层次结构。翻转的 VEV 应该存在于 NSClipView 和 NSPredicateEditor 之间。

然后添加自动布局约束,如下所示。不要约束 VEV 的底部或高度锚点。


注:

  • 设置 scrollView.documentView = flippedVEV 修复滚动。

  • 如果您不使用 isFlipped VEV,则谓词编辑器行堆叠在底部而不是顶部。


class FlippedVEV: NSVisualEffectView {
    override var isFlipped: Bool { return true }
}

class PredicateEditorViewController: NSViewController {

    @IBOutlet weak var predicateEditor: NSPredicateEditor!

    override func viewDidLoad() {
        super.viewDidLoad()

        if let clipView = predicateEditor.superview as? NSClipView, let scrollView = clipView.superview as? NSScrollView {
            let flippedVEV = FlippedVEV(frame: predicateEditor.frame)
            flippedVEV.material = .sheet

            predicateEditor.removeFromSuperview()
            flippedVEV.addSubview(predicateEditor)
            clipView.addSubview(flippedVEV)
            scrollView.documentView = flippedVEV

            flippedVEV.translatesAutoresizingMaskIntoConstraints = false
            NSLayoutConstraint.activate([
                flippedVEV.leadingAnchor .constraint(equalTo:predicateEditor.leadingAnchor ),
                flippedVEV.trailingAnchor.constraint(equalTo:predicateEditor.trailingAnchor),
                flippedVEV.topAnchor     .constraint(equalTo:predicateEditor.topAnchor     ),
                flippedVEV.bottomAnchor  .constraint(equalTo:predicateEditor.bottomAnchor  ),
                clipView.leadingAnchor   .constraint(equalTo:flippedVEV     .leadingAnchor ),
                clipView.trailingAnchor  .constraint(equalTo:flippedVEV     .trailingAnchor),
                clipView.topAnchor       .constraint(equalTo:flippedVEV     .topAnchor     ),
            ])
        }
    }

}