如何使用 SwiftUI 在 macOS 上可靠地检索窗口的背景颜色?

vma*_*let 9 macos swift swiftui

是否有一种 Swifty 方法可以检测 macOS 上 SwiftUI 中窗口的背景颜色,无论当前主题如何(深色模式或浅色模式),该方法都可以可靠地工作?

例如,如果要制作一个与窗口背景“融合”的实心矩形,他们会使用哪种颜色?

这个答案建议使用NSColor.xxxBackgroundColorSwiftUI:获取动态背景颜色(深色模式或浅色模式)

然而,这对我来说不太管用。下面是一些测试代码(Xcode 12.5,Swift 5.4),它生成了三个不同NSColors 的矩形。我正在寻找一种与背景融为一体的。

struct TestView: View {
    var body: some View {
        VStack(spacing: 20) {
            Text("This text is on the default background")
            HStack(spacing: 30) {
                Text("windowBackgroundColor")
                    .frame(width: 200, height: 100)
                    .background(Color(NSColor.windowBackgroundColor))
                Text("underPageBackgroundColor")
                    .frame(width: 200, height: 100)
                    .background(Color(NSColor.underPageBackgroundColor))
                Text("textBackgroundColor")
                    .frame(width: 200, height: 100)
                    .background(Color(NSColor.textBackgroundColor))
            }
        }
        .padding(20)
    }
}
Run Code Online (Sandbox Code Playgroud)

在深色模式下,它似乎NSColor.underPageBackgroundColor与窗口的背景相匹配。 在此输入图像描述

但在 Light 模式下,没有任何匹配: 在此输入图像描述

Alb*_*tUI 12

快速获取窗口背景的方法

窗口的背景不是由颜色组成的,是NSVisualEffectView带有.windowBackgroundas 的material

您可以使用以下代码来实现:

struct EffectView: NSViewRepresentable {
    @State var material: NSVisualEffectView.Material = .headerView
    @State var blendingMode: NSVisualEffectView.BlendingMode = .withinWindow

    func makeNSView(context: Context) -> NSVisualEffectView {
        let view = NSVisualEffectView()
        view.material = material
        view.blendingMode = blendingMode
        return view
    }
    
    func updateNSView(_ nsView: NSVisualEffectView, context: Context) {
        nsView.material = material
        nsView.blendingMode = blendingMode
    }
}
Run Code Online (Sandbox Code Playgroud)

并将其应用到您的视图中:

struct ContentView: View {
    var body: some View {
        EffectView(material: .windowBackground)
            .overlay(Text("Window Real Background"))
            .padding(30)
    }
}
Run Code Online (Sandbox Code Playgroud)

输出是这样的(没有什么可看的,因为它模仿了背景):

在此输入图像描述

背景之所以是 NSVisualEffectView 是因为 macOS Big Sur 的 Window Tinting,它会根据壁纸的主要颜色更改背景:

在此输入图像描述