• 如何使用 SwiftUI 支持夜色模式?


    【中文标题】如何使用 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 矩形。我正在寻找与背景融为一体的那个。

    1. struct TestView: View
    2. var body: some View
    3. VStack(spacing: 20)
    4. Text("This text is on the default background")
    5. HStack(spacing: 30)
    6. Text("windowBackgroundColor")
    7. .frame(width: 200, height: 100)
    8. .background(Color(NSColor.windowBackgroundColor))
    9. Text("underPageBackgroundColor")
    10. .frame(width: 200, height: 100)
    11. .background(Color(NSColor.underPageBackgroundColor))
    12. Text("textBackgroundColor")
    13. .frame(width: 200, height: 100)
    14. .background(Color(NSColor.textBackgroundColor))
    15. .padding(20)

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

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

    【问题讨论】:

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

    获取窗口背景的快捷方式

    窗口的背景不是由颜色组成的,是NSVisualEffectView 和.windowBackground 为material

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

    1. struct EffectView: NSViewRepresentable
    2. @State var material: NSVisualEffectView.Material = .headerView
    3. @State var blendingMode: NSVisualEffectView.BlendingMode = .withinWindow
    4. func makeNSView(context: Context) -> NSVisualEffectView
    5. let view = NSVisualEffectView()
    6. view.material = material
    7. view.blendingMode = blendingMode
    8. return view
    9. func updateNSView(_ nsView: NSVisualEffectView, context: Context)
    10. nsView.material = material
    11. nsView.blendingMode = blendingMode

    并将其应用于您的视图:

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

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

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

    【讨论】:

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

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

    1. @Environment(\.colorScheme) var colorScheme
    2. struct TestView: View
    3. var body: some View
    4. VStack(spacing: 20)
    5. Text("This text is on the default background")
    6. HStack(spacing: 30)
    7. Text("windowBackgroundColor")
    8. .frame(width: 200, height: 100)
    9. .background(colorScheme == .dark ? Color.black : Color.white)
    10. Text("underPageBackgroundColor")
    11. .frame(width: 200, height: 100)
    12. .background(colorScheme == .dark ? Color.black : Color.white)
    13. Text("textBackgroundColor")
    14. .frame(width: 200, height: 100)
    15. .background(colorScheme == .dark ? Color.black : Color.white)
    16. .background(colorScheme == .dark ? Color.black : Color.white)
    17. .padding(20)

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

    1. var windowBGColor = NSColor.windowBackgroundColor
    2. var underPageBGColor = NSColor.underPageBackgroundColor
    3. var textBGColor = NSColor.textBackgroundColor
    4. var sampleColor = colorScheme == .dark ? windowBGColor : textBGColor

    【讨论】:

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

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

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

  • 相关阅读:
    阿里云国际版忘记会员名或登录密码,怎么办?
    OpenMMLab【超级视客营】——支持InverseForm Loss(MMSegmentation的第三个PR)
    grid项目属性之grid-area&justify-self/align-self
    LMI相机配置步骤,使用Gocator2550相机
    leetcode竞赛:85 场双周赛
    6.2、Flink数据写入到Kafka
    算法刷题-动态规划2
    基于.NetCore开发博客项目 StarBlog - (27) 使用JWT保护接口
    【PyTorch深度学习项目实战100例】—— 基于ViT(Vision_Transformer)识别七龙珠超级赛亚人 | 第52例
    【LabVIEW 】串口如何读取长度不一致的字符串
  • 原文地址:https://blog.csdn.net/weixin_42610770/article/details/132725618