我正在制作一个位于状态栏中的应用。单击状态项时,将弹出NSPopover。
看起来像这样:
问题在于:我希望它是“瞬态的”,即如果我点击弹出窗口外的任何地方,它就会关闭。虽然当弹出窗口在窗口中时NSPopoverBehaviorTransient正常工作,但当它处于状态栏时它不起作用。
我如何自己实施此类行为?
答案 0 :(得分:28)
结果很简单:
- (IBAction)openPopover:(id)sender
{
// (open popover)
if(popoverTransiencyMonitor == nil)
{
popoverTransiencyMonitor = [NSEvent addGlobalMonitorForEventsMatchingMask:NSLeftMouseDownMask|NSRightMouseDownMask handler:^(NSEvent* event)
{
[self closePopover:sender];
}];
}
}
- (IBAction)closePopover:(id)sender
{
if(popoverTransiencyMonitor)
{
[NSEvent removeMonitor:popoverTransiencyMonitor];
popoverTransiencyMonitor = nil;
}
// (close popover)
}
但是,不容易的是,有一个令人讨厌的问题,就是有一个弹出窗口弹出NSStatusItem(当调用Mission Control或空间切换到全屏窗口时,它没有按预期运行)。我必须实现一个总是漂浮在NSStatusItem之上的自定义窗口,并处理切换到全屏窗口等。这似乎很容易,但显然状态项不是为那样的东西设计的;)
答案 1 :(得分:8)
我使用的方法类似于上面的答案,除了我将所有内容合并为一个方法而不是使用两个单独的IBAction。
首先,我宣布以下属性
@property (strong, nonatomic) NSStatusItem *statusItem;
@property (strong, nonatomic) NSEvent *popoverTransiencyMonitor;
@property (weak, nonatomic) IBOutlet NSPopover *popover;
@property (weak, nonatomic) IBOutlet NSView *popoverView;
然后在awakeFromNib中设置状态栏项
- (void)awakeFromNib {
self.statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];
self.statusItem.title = @"Title";
self.statusItem.highlightMode = YES;
self.statusItem.action = @selector(itemClicked:);
}
后跟单击状态栏项时调用的方法
- (void)itemClicked:(id)sender {
[[self popover] showRelativeToRect:[sender bounds] ofView:sender preferredEdge:NSMinYEdge];
if (self.popoverTransiencyMonitor == nil) {
self.popoverTransiencyMonitor = [NSEvent addGlobalMonitorForEventsMatchingMask:(NSLeftMouseDownMask | NSRightMouseDownMask | NSKeyUpMask) handler:^(NSEvent* event) {
[NSEvent removeMonitor:self.popoverTransiencyMonitor];
self.popoverTransiencyMonitor = nil;
[self.popover close];
}];
}
}
,当用户在视图外部点击时,弹出窗口会显示并关闭。
请注意,在Interface Builder中,您必须将弹出窗口的行为设置为Transient,以便在用户单击状态项时弹出框将关闭。