从NSToolbarItem按钮显示NSPopover



我想在工具栏中显示NSToolbarItem按钮中的NSPopover
(即位于按钮下方)。

理想情况下,我想把按钮的NSView传递给弹出窗口来定位它。
我的问题是,我如何得到NSToolbarItemNSView ?

[toolbarbutton view]总是返回nil

答案似乎在2011年WWDC第113次会议的视频中,"全屏和Aqua变化"。基本上,把一个NSButton放到NSToolbaritem中并使用它的视图。

博客文章在这里:http://www.yellowfield.co.uk/blog/?p=33,一个示例项目在github上http://github.com/tevendale/ToolbarPopover

都在http://xkcd.com/979的精神!

您可以直接从NSToolbarItem中包含的NSButton发送动作(这是您通常应该做的,无论如何,考虑分段控制,其中每个段都有自己的目标/动作),这将做到这一点。

不是从IBAction发送器获取视图,而是直接将IBOutlet连接到工具栏项,并使用它来获取相对视图:

头文件:

@property (weak) IBOutlet NSToolbarItem *theToolbarItem;
@property (weak) IBOutlet NSPopover *thePopover;

在你的实现文件中,要显示弹出窗口:

[self.thePopover showRelativeToRect:[[self.theToolbarItem view] bounds] ofView:[self.theToolbarItem view] preferredEdge:NSMinYEdge];

这也可以用于在工具栏项中显示菜单项选择的弹出窗口

虽然我确实实现了使用Stuart Tevendale提到的方法显示弹出窗口,但当我试图使用NSToolbarDelegate:

验证(启用/禁用)NSToolbarItems时,我确实遇到了问题。
-(BOOL)validateToolbarItem:(NSToolbarItem *)toolbarItem {
    BOOL enable = YES;
    NSString *identifier = [toolbarItem itemIdentifier];
    // This does never get called because I am using a button inside a custom `NSToolbarItem`
    if ([identifier isEqualToString:@"Popover"]) {
        return [self someValidationMechanism];
    } 
    // For this the validation works when I am using a standard `NSToolbarItem`
    else if ([identifier isEqualToString:@"StandardToolbarItem"]){
        return [self someOtherValidationMechanism];
    }
    return enable;
}

所以我建议不要显示从NSToolbarItem弹出窗口。另一种选择可能是显示一个页表:如何显示一个NSPanel作为一个工作表

您可以获得toolbarItemview如下代码:

guard let itemViewer = toolbarItem.value(forKey: "_itemViewer") as? NSView else {
      return
}
let shareServicePicker = NSSharingServicePicker(items: pathUrls)
shareServicePicker.delegate = self
shareServicePicker.show(relativeTo: itemViewer.bounds, of: itemViewer, preferredEdge: .maxY)

最新更新