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

     2023-02-24     144

关键词:

【中文标题】如何使用 SwiftUI 在 macOS 上可靠地检索窗口的背景颜色?【英文标题】:How to reliably retrieve a window's background color on macOS with SwiftUI? 【发布时间】:2021-04-28 16:54:22 【问题描述】:

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

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

这个答案建议使用NSColor.xxxBackgroundColor: SwiftUI: Get the Dynamic Background Color (Dark Mode or Light Mode)

但是,这对我来说不太适用。下面是一些测试代码(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)
    

在深色模式下,NSColor.underPageBackgroundColor 似乎与窗口的背景相匹配。

但在 Light 模式下,没有匹配项:

【问题讨论】:

您是在寻找背景提供的颜色还是检查主题?你的问题不是很清楚,我也不能 100% 确定我的答案是否正确。 @xTwisteDx 确实在寻找窗口背景提供的颜色。让我看看我是否可以澄清这个问题。 我猜我要问的是,你想用这些颜色做什么?从我的角度来看,你似乎已经有了颜色,所以对它们做你想做的事。我觉得你需要解释你的预期结果是什么。您似乎已经可靠地获取了您正在寻找的颜色。 啊,我明白了。您需要设置该颜色,否则它不会像您预期的那样显示。无法从视图中“获取”颜色,但是您可以设置颜色。我现在正在更新我的答案。 【参考方案1】:

获取窗口背景的快捷方式

窗口的背景不是由颜色组成的,是NSVisualEffectView.windowBackgroundmaterial

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

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
    

并将其应用于您的视图:

struct ContentView: View 
    var body: some View 
        EffectView(material: .windowBackground)
            .overlay(Text("Window Real Background"))
            .padding(30)
    

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

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

【讨论】:

美丽的东西!事实上,使用.windowBackground 作为材料,我可以使用 EffectView 作为背景并获得我正在寻找的效果。感谢您的基本解释。【参考方案2】:

您可以使用@Environment 变量来获取正在生成的ColorScheme。在 iOS 中,我经常这样使用它,但它也应该转换为 MacOS。无法动态获取视图的颜色,因为它是一个不可访问的设定值。您可以做的最好的事情是将视图设置为已知状态,然后根据需要传递该颜色。在我的示例中,我只使用了Color.black and Color.white,但您可以轻松地将任何颜色分配给变量并将其传递给已知值。

@Environment(\.colorScheme) var colorScheme

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(colorScheme == .dark ? Color.black : Color.white)
                Text("underPageBackgroundColor")
                    .frame(width: 200, height: 100)
                    .background(colorScheme == .dark ? Color.black : Color.white)
                Text("textBackgroundColor")
                    .frame(width: 200, height: 100)
                    .background(colorScheme == .dark ? Color.black : Color.white)
            
        
        .background(colorScheme == .dark ? Color.black : Color.white)
        .padding(20)
    

在您的情况下,您可以将颜色替换为您想要使用的系统颜色。基于colorScheme 设置您想要在该视图上使用的特定颜色。比如……

var windowBGColor = NSColor.windowBackgroundColor
var underPageBGColor = NSColor.underPageBackgroundColor
var textBGColor = NSColor.textBackgroundColor

var sampleColor = colorScheme == .dark ? windowBGColor : textBGColor

【讨论】:

谢谢。这是我用来使事情正常工作的解决方法(即将窗口上的背景颜色设置为与当前配色方案有点合作的已知值)但我希望找到一种更可靠的方法来了解实际使用的颜色在运行时使事情更具未来性。真的感觉NSColor.windowBackroundColor应该是它。【参考方案3】:

windowBackground 是真实窗口的背景颜色,您只需将其与真实窗口背景进行比较,而不是与主机控制器视图下方的主题视图进行比较

这是一个层次结构(你可以在视图调试模式下自己验证)

【讨论】:

这让我发现了非常有用的视图调试器,谢谢。

如何使用 SwiftUI 在 MacOS 上配置多选分段控制

】如何使用SwiftUI在MacOS上配置多选分段控制【英文标题】:Howtoconfiguremulti-selectSegmentedControlonMacOSwithSwiftUI【发布时间】:2020-05-1700:24:21【问题描述】:macOSHIG建议分段控件可以是多选的:https://developer.apple.com/design/human-interface-guid... 查看详情

如何在 macOS 上检测 SwiftUI 中的键盘事件?

】如何在macOS上检测SwiftUI中的键盘事件?【英文标题】:HowtodetectkeyboardeventsinSwiftUIonmacOS?【发布时间】:2020-04-1107:44:08【问题描述】:如何在macOS上的SwiftUI视图中检测键盘事件?我希望能够使用击键来控制特定屏幕上的项目,但... 查看详情

如何在 macOS 上检测 SwiftUI 中的键盘事件?

】如何在macOS上检测SwiftUI中的键盘事件?【英文标题】:HowtodetectkeyboardeventsinSwiftUIonmacOS?【发布时间】:2020-04-1107:44:08【问题描述】:如何在macOS上的SwiftUI视图中检测键盘事件?我希望能够使用击键来控制特定屏幕上的项目,但... 查看详情

SwiftUI:如何在 macOS 11 上设置工具栏的标题?

】SwiftUI:如何在macOS11上设置工具栏的标题?【英文标题】:SwiftUI:HowtosetthetitleforthetoolbaronmacOS11?【发布时间】:2020-10-1419:21:16【问题描述】:我有一个SwiftUI应用程序,它有两列和一个工具栏。我正在尝试模拟最新的macOS应用程... 查看详情

SwiftUI - 如何在 macOS 上隐藏窗口标题

】SwiftUI-如何在macOS上隐藏窗口标题【英文标题】:SwiftUI-HowtohidewindowtitleonmacOS【发布时间】:2020-12-0317:48:58【问题描述】:在没有AppDelegate/SceneDelegate的新SwiftUI框架的macOS上,如何隐藏窗口标题?我发现这篇来自Apple的文章描述了... 查看详情

如何在 SwiftUI MacOS App 中使用 NSTouchBar?

】如何在SwiftUIMacOSApp中使用NSTouchBar?【英文标题】:HowcanIuseNSTouchBarinSwiftUIMacOSApp?【发布时间】:2020-05-0815:45:41【问题描述】:我正在尝试在SwiftUI中为我的MacOS应用程序添加TouchBar支持。我发现我必须打电话..NSApp.isAutomaticCustomize... 查看详情

在 MacOS 上构建 SwiftUI “Hello World”

】在MacOS上构建SwiftUI“HelloWorld”【英文标题】:BuildSwiftUI"HelloWorld"onMacOS【发布时间】:2019-06-1112:16:19【问题描述】:SwiftUI“HelloWorld”适用于iOS,但不适用于MacOS。尝试构建一个简单的“HelloWorld”SwiftUI示例以查看它在Mac... 查看详情

为啥相同的 SwiftUI 代码可以在 iOS 上运行而在 macOS 上失败?

】为啥相同的SwiftUI代码可以在iOS上运行而在macOS上失败?【英文标题】:WhydoesidenticalSwiftUIcodeworkoniOSandfailonmacOS?为什么相同的SwiftUI代码可以在iOS上运行而在macOS上失败?【发布时间】:2021-04-2910:28:57【问题描述】:我使用Multiplat... 查看详情

如何使用 getusermedia 让网络摄像头在 Firefox 上可靠地工作?

】如何使用getusermedia让网络摄像头在Firefox上可靠地工作?【英文标题】:HowcanIgetthewebcamtoworkreliablyonFirefoxusinggetusermedia?【发布时间】:2022-01-1304:20:04【问题描述】:我正在设计一个网站来教授因纽特手语,它在多个页面上使用... 查看详情

(SwiftUI, MacOS 11.0) 如何在 SecureTextFeild 中检测焦点?

】(SwiftUI,MacOS11.0)如何在SecureTextFeild中检测焦点?【英文标题】:(SwiftUI,MacOS11.0)HowtodetectfocusinSecureTextFeild?【发布时间】:2021-07-2203:57:42【问题描述】:我正在使用SwiftUI开发一个新的macOS应用程序,但不知道如何在SecureTextFeild中检... 查看详情

SwiftUI:如何在 macOS 应用程序中实现编辑菜单

】SwiftUI:如何在macOS应用程序中实现编辑菜单【英文标题】:SwiftUI:HowtoimplementEditmenuinmacOSapp【发布时间】:2021-02-1320:38:10【问题描述】:我正在使用SwiftUI和新的App生命周期构建一个macOS应用程序。开始新项目后,所有默认的macOS... 查看详情

使用 SwiftUI 在 MacOS 中的多列 TableViews

】使用SwiftUI在MacOS中的多列TableViews【英文标题】:MultiColumnTableViewsinMacOSusingSwiftUI【发布时间】:2020-02-2506:16:23【问题描述】:我一直在用SWiftUI进行一些试验,但似乎根本找不到任何关于如何使用SWiftUI创建多列TableView的信息,... 查看详情

如何在 iPhone 上可靠地获取位置

】如何在iPhone上可靠地获取位置【英文标题】:HowtoreliablyacquirelocationontheiPhone【发布时间】:2010-02-0117:28:33【问题描述】:我正在开发一个使用iPhoneGPS获取位置轨迹的应用程序。为了省电,我想在屏幕关闭时获取位置数据。我已... 查看详情

如何让 SwiftUI SidebarMenu 每次都显示相同的 DetailView 而不是创建一个新的(在 macOS 上)

】如何让SwiftUISidebarMenu每次都显示相同的DetailView而不是创建一个新的(在macOS上)【英文标题】:HowcanIgetaSwiftUISidebarMenutodisplaythesameDetailVieweachtimeratherthancreatinganewone(onmacOS)【发布时间】:2020-03-1310:15:12【问题描述】:我有一个ma... 查看详情

SwiftUI 2.0 在 macOS 上禁用窗口的缩放按钮

】SwiftUI2.0在macOS上禁用窗口的缩放按钮【英文标题】:SwiftUI2.0disablewindow\'szoombuttononmacOS【发布时间】:2021-02-0302:58:39【问题描述】:我正在为Mac编写一个小应用程序..我需要禁用(绿色按钮)才能全屏。我使用的是SwiftUIApp而不... 查看详情

在 MacOS 上的 SwiftUI 中查找点击位置

】在MacOS上的SwiftUI中查找点击位置【英文标题】:FindingclicklocationinSwiftUIonMacOS【发布时间】:2020-11-2805:46:24【问题描述】:我尝试使用NSViewRepresentable而不是UIViewRepresentable将我在iOS应用程序上使用的解决方案调整到macOS。下面是... 查看详情

SwiftUI - 在 macOS 上翻转全局坐标空间

】SwiftUI-在macOS上翻转全局坐标空间【英文标题】:SwiftUI-GlobalcoordinatespaceisflippedonmacOS【发布时间】:2020-11-2714:29:51【问题描述】:编辑:已确认是Apple错误。现在已在macOSMonterey上修复在我看来,通过GeometryReader阅读框架在macOS上... 查看详情

SwiftUI:WKWebView 在 macOS 上截断页面内容(NSViewRepresentable)

】SwiftUI:WKWebView在macOS上截断页面内容(NSViewRepresentable)【英文标题】:SwiftUI:WKWebViewCuttingOffPageContentonmacOS(NSViewRepresentable)【发布时间】:2019-12-1520:50:57【问题描述】:我有一个基本的NSViewRepresentable实现WKWebView,用于macOS上的Sw... 查看详情