簡體   English   中英

彈出窗口處於活動狀態時突出顯示狀態按鈕(Swift、macOS)

[英]Status button highlight when popover is active (Swift, macOS)

我正在制作狀態欄 macOS 應用程序。 單擊狀態欄圖標時,我會顯示 NSPopover(不是 NSMenu)。 但是,當顯示我的 NSPopover 時,我的狀態菜單圖標未突出顯示。 當我單擊它時,它只會突出顯示片刻。 我希望它保持突出顯示,就像它在 wifi 狀態欄圖標上的表現一樣。

我知道如果我使用 NSMenu 而不是 NSPopover,它可能會被修復。 但要求是我需要使用 NSPopover。

我嘗試了以下方法,但無濟於事:

1.

let statusItem = NSStatusBar.system.statusItem(withLength:NSStatusItem.squareLength)
if let button = statusItem.button {
    button.setButtonType(.pushOnPushOff)
}
statusItem.highlightMode = true
statusItem.button?.highlight(true)
statusItem.button?.isHighlighted = true

我對狀態欄應用程序不是很有經驗。 所以我不太確定在這里采用哪種方法。

最左邊的圖標是我的狀態欄應用程序圖標。 彈出窗口當前處於活動狀態,但圖標未突出顯示。 我不得不剪掉彈出窗口。

最左邊的圖標是我的狀態欄應用程序圖標。彈出窗口當前處於活動狀態,但圖標未突出顯示。我不得不剪掉彈出窗口。

這可以做到,但要可靠地做到這一點需要一些緊密的耦合。 在這個例子中,我假設你有一個名為NSViewControllerPopoverController ,它有一個togglePopover()方法,並且你已經將這個 controller 設置為狀態欄按鈕的目標。

第 0 步:上下文

這是控制彈出窗口的 class 的基本設置:

final class PopoverController: NSViewController
{
    private(set) var statusItem: NSStatusItem!
    private(set) var popover: NSPopover


    // You can set up your StatusItem and Popover anywhere; but here's an example with -awakeFromNib()
    override func awakeFromNib()
    {
        super.awakeFromNib()

        statusItem = NSStatusBar.system.statusItem(withLength: 20.0)
        statusItem.button?.sendAction(on: [.leftMouseDown, .rightMouseDown])
        statusItem.button?.image = NSImage(named: "statusBar-icon")
        statusItem.button?.target = self
        statusItem.button?.action = #selector(togglePopover)

        popover = NSPopover()
        popover.behavior = .transient
        popover.delegate = self
        popover.contentViewController = self
        popover.setValue(true, forKeyPath: "shouldHideAnchor")      // Private API
    }


    @objc func togglePopover()
    {
        if popover.isShown
        {
            popover.performClose(nil)
        }
        else if !popover.isShown,
                let button: NSButton = statusItem.button,
                button.window?.contentView != nil,              // Exception thrown if view is nil or not part of a window.
                button.superview != nil
        {
            popover.show(relativeTo: .zero, of: button, preferredEdge: .minY)
        }
    }
}

第 1 步:覆蓋狀態按鈕

extension NSStatusBarButton
{
    public override func mouseDown(with event: NSEvent)
    {
        if event.modifierFlags.contains(.control)
        {
            self.rightMouseDown(with: event)
            return
        }
        
        if let controller: PopoverController = self.target as? PopoverController
        {
            controller.togglePopover()
            self.highlight(controller.popover.isShown)
        }
    }
}

第 2 步:處理 Popover 關閉

確保PopoverController符合NSPopoverDelegate並實現此委托方法:

func popoverDidClose(_ notification: Notification)
{
    statusItem.button?.highlight(false)
}

結果

所有這些都准備就緒后,按鈕突出顯示現在就像它對 Apple 的系統狀態欄項目(如控制中心、Wifi、電池等)一樣工作。

注意:您還需要添加一個全局事件監視器來監聽在您的彈出窗口之外發生的點擊,以確保當用戶點擊遠離它時它正確關閉。 但這在這個問題的 scope 之外,並且可以在 SO 的其他地方找到。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM