【问题标题】:Swift ui mac os menubar popover change backgroundSwiftui macos 菜单栏弹出框更改背景
【发布时间】:2021-09-27 05:27:24
【问题描述】:

从图片中可以看出,我有menu bar popover,即transparent,我希望它是一种特定的颜色。

我该怎么办,你能帮帮我吗?

状态栏控制器

import AppKit
import SwiftUI

class StatusBarController {
    @ObservedObject var userPreferences = UserPreferences.instance
    private var statusBar: NSStatusBar
    var statusItem: NSStatusItem
    private var popover: NSPopover
    
    init(_ popover: NSPopover) {
        self.popover = popover
        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)
    }
    
}

AppDelegate

import Cocoa
import SwiftUI

@main
class AppDelegate: NSObject, NSApplicationDelegate {
    var statusBar: StatusBarController?
    var popover = NSPopover.init()
    
    var timer: Timer? = nil

    func applicationDidFinishLaunching(_ aNotification: Notification) {
        let contentView = ContentView()
        popover.contentSize = NSSize(width: 360, height: 360)
        popover.contentViewController = NSHostingController(rootView: contentView)
        statusBar = StatusBarController.init(popover)
    }

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

【问题讨论】:

  • 看起来您使用的是 AppKit UI(例如 NSPopover)而不是 SwiftUI(Popover)。我在这里看到的唯一 SwiftUI 构造是 @main。也许重新标记这个问题?还是将实现切换到 SwiftUI?

标签: swift macos popover appkit nspopover


【解决方案1】:

参考:https://www.programmersought.com/article/29256315686/

结果:

使用这个扩展:

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
        }
    }
}

用法:

self.popover = popover
self.popover.backgroundColor = #colorLiteral(red: 0.3411764801, green: 0.6235294342, blue: 0.1686274558, alpha: 1)

【讨论】:

  • 它似乎可以工作,但如果我使用透明胶片就会出现问题。
  • 用您现在面临的“问题”更新您的问题。
  • 从图片中可以看出,如果我使用透明度,您会注意到箭头和内容之间的差异。 user-images.githubusercontent.com/20476002/…
  • 如果用 AlphaComponent 添加颜色,它会给出想要的外观吗?
  • self.popover.backgroundColor = #colorLiteral(red: 0.2588235438, green: 0.7568627596, blue: 0.9686274529, alpha: 0.5109410708)
猜你喜欢
  • 1970-01-01
  • 2016-03-16
  • 1970-01-01
  • 2014-09-06
  • 1970-01-01
  • 2014-02-09
  • 1970-01-01
  • 1970-01-01
  • 2019-11-22
相关资源
最近更新 更多