5

我正在NSPopover使用状态栏中的图标操作打开一个。

myPopover.show(relativeTo: button.bounds, of: button, preferredEdge: NSRectEdge.minY)

除了从弹出框和系统栏的距离为零之外,这可以正常工作:

在此处输入图像描述

我想达到与 Dropbox 应用程序相同的结果,它在距离系统栏很近的地方呈现弹出框:

在此处输入图像描述

我试过使用button.bounds.offsetBy(dx: 0.0, dy: 20.0)which 不会影响弹出框的位置button.bounds.offsetBy(dx: 0.0, dy: -20.0)并将弹出框放在系统栏上方:

在此处输入图像描述

那么如何将其定位NSPopover在距系统栏一定距离的位置?

4

2 回答 2

8

button.bounds.offsetBy(dx: 0.0, dy: -20.0)首先,不起作用的原因是因为这些坐标落在状态栏项目的“窗口”之外,即状态栏本身。所以它之外的任何东西都被裁剪了。

我通过在这里和那里收集信息解决了这个问题:

  1. 创建一个不可见的窗口。
  2. 找到状态栏项目在屏幕中的坐标,将不可见的窗口定位在其下方。
  3. 显示与NSPopover不可见窗口相关的,而不是状态栏项目。

在此处输入图像描述

红色的东西是不可见的窗口(用于演示目的)。

斯威夫特 4 (Xcode 9.2)

// Create a window
let invisibleWindow = NSWindow(contentRect: NSMakeRect(0, 0, 20, 5), styleMask: .borderless, backing: .buffered, defer: false)
invisibleWindow.backgroundColor = .red
invisibleWindow.alphaValue = 0

if let button = statusBarItem.button {
    // find the coordinates of the statusBarItem in screen space
    let buttonRect:NSRect = button.convert(button.bounds, to: nil)
    let screenRect:NSRect = button.window!.convertToScreen(buttonRect)

    // calculate the bottom center position (10 is the half of the window width)
    let posX = screenRect.origin.x + (screenRect.width / 2) - 10
    let posY = screenRect.origin.y

    // position and show the window
    invisibleWindow.setFrameOrigin(NSPoint(x: posX, y: posY))
    invisibleWindow.makeKeyAndOrderFront(self)

    // position and show the NSPopover
    mainPopover.show(relativeTo: invisibleWindow.contentView!.frame, of: invisibleWindow.contentView!, preferredEdge: NSRectEdge.minY)
    NSApp.activate(ignoringOtherApps: true)
}

我试图使用show(relativeTo: invisibleWindow.frame ...)并且弹出窗口没有出现,因为NSWindow它不是NSView. 要显示弹出窗口,必须通过视图。

于 2018-02-04T03:41:22.043 回答
0

您可以在显示后立即移动 popover 的 contentView:

myPopover.show(relativeTo: button.bounds, of: button, preferredEdge: NSRectEdge.minY)

let popoverWindowX = myPopover.contentViewController?.view.window?.frame.origin.x ?? 0
let popoverWindowY = myPopover.contentViewController?.view.window?.frame.origin.y ?? 0

myPopover.contentViewController?.view.window?.setFrameOrigin(
    NSPoint(x: popoverWindowX, y: popoverWindowY + 20)
)

myPopover.contentViewController?.view.window?.makeKey()

在 UI 方面,您会看到箭头的轻微滑动,但在您的情况下,使用非常小的填充,它将是最难以察觉的。

我正在使用类似的东西来确保我的弹出框不会离开屏幕。你可以看到轻微的滑动。

弹出框滑动

于 2022-02-20T16:33:10.120 回答