繁体   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