Swift macOS popover 检测更改暗模式 [英] Swift macOS popover detect change dark mode

查看:26
本文介绍了Swift macOS popover 检测更改暗模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从图片中可以看出我有一个弹出框.

I have a popover as seen from the image.

我必须确保当屏幕模式改变时,无论是暗模式还是亮模式,弹出框的颜色都会发生变化.

I have to make sure that when the screen mode changes, dark mode or light mode, the color of the popover changes.

颜色取自资产,如下所示:

The color is taken from the asset, like this:

NSColor(named: "backgroundTheme")?.withAlphaComponent(1)

正如您在 init 函数中启动弹出框时的代码所见,我相应地分配了颜色.

As you can see from the code when starting the popover in the init function I assign the color accordingly.

如何拦截模式的变化?

你能帮我一把吗?

应用程序委托:

import Cocoa
import SwiftUI

@main
class AppDelegate: NSObject, NSApplicationDelegate {
    var popover = NSPopover.init()
    var statusBar: StatusBarController?
    
    func applicationDidFinishLaunching(_ aNotification: Notification) {
        let contentView = ContentView()
        popover.contentSize = NSSize(width: 560, height: 360)
        popover.contentViewController = NSHostingController(rootView: contentView)
        statusBar = StatusBarController.init(popover)
    }

    func applicationWillTerminate(_ aNotification: Notification) {
        // Insert code here to tear down your application
    }
}

状态栏控制器:

import AppKit
import SwiftUI

extension NSPopover {
    
    private struct Keys {
        static var backgroundViewKey = "backgroundKey"
    }
    
    private var backgroundView: NSView {
        let bgView = objc_getAssociatedObject(self, &Keys.backgroundViewKey) as? NSView
        if let view = bgView {
            return view
        }
        
        let view = NSView()
        objc_setAssociatedObject(self, &Keys.backgroundViewKey, view, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        NotificationCenter.default.addObserver(self, selector: #selector(popoverWillOpen(_:)), name: NSPopover.willShowNotification, object: nil)
        return view
    }
    
    @objc private func popoverWillOpen(_ notification: Notification) {
        if backgroundView.superview == nil {
            if let contentView = contentViewController?.view, let frameView = contentView.superview {
                frameView.wantsLayer = true
                backgroundView.frame = NSInsetRect(frameView.frame, 1, 1)
                backgroundView.autoresizingMask = [.width, .height]
                frameView.addSubview(backgroundView, positioned: .below, relativeTo: contentView)
            }
        }
    }
    
    var backgroundColor: NSColor? {
        get {
            if let bgColor = backgroundView.layer?.backgroundColor {
                return NSColor(cgColor: bgColor)
            }
            return nil
        }
        set {
            backgroundView.wantsLayer = true
            backgroundView.layer?.backgroundColor = newValue?.cgColor
        }
    }
}

class StatusBarController {
    private var popover: NSPopover
    private var statusBar: NSStatusBar
    var statusItem: NSStatusItem

    
    init(_ popover: NSPopover) {
        self.popover = popover
        self.popover.backgroundColor = NSColor(named: "backgroundTheme")?.withAlphaComponent(1)
        statusBar = NSStatusBar.init()
        statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
        
        if let statusBarButton = statusItem.button {
            statusBarButton.image = #imageLiteral(resourceName: "Fork")
            statusBarButton.image?.size = NSSize(width: 18.0, height: 18.0)
            statusBarButton.image?.isTemplate = true
            statusBarButton.action = #selector(togglePopover(sender:))
            statusBarButton.target = self
            statusBarButton.imagePosition = NSControl.ImagePosition.imageLeft
        }
    }
    
    @objc func togglePopover(sender: AnyObject) {
        if(popover.isShown) {
            hidePopover(sender)
        }else {
            showPopover(sender)
        }
    }
    
    func showPopover(_ sender: AnyObject) {
        if let statusBarButton = statusItem.button {
            popover.show(relativeTo: statusBarButton.bounds, of: statusBarButton, preferredEdge: NSRectEdge.maxY)
        }
    }
    
    func hidePopover(_ sender: AnyObject) {
        popover.performClose(sender)
    }
    
}

推荐答案

我会跳过在弹出框上设置颜色,而是在 ContentView.swift 中设置背景

Hi I would skip setting the color on the popover and instead set the background in your ContentView.swift

然后将背景设置为包装 UI 其余部分的 VStack/HStack/ZStack.

Then set the background to a VStack/HStack/ZStack wrapping the rest of the UI.

var body: some View {
        VStack{
            Text("Hello, world!").padding()
            Button("Ok", action: {}).padding()
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(Color("backgroundTheme").opacity(0.3))
        .padding(.top, -16)
    }

这篇关于Swift macOS popover 检测更改暗模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆