18

ステータスバーに住むアプリを作っています。ステータス項目をクリックすると、NSPopover がポップアップします。

次のようになります。

ここに画像の説明を入力

問題は次のとおりです。「一時的」にしたいのです。つまり、ポップオーバーの外側のどこかをクリックすると、ポップオーバーが閉じます。NSPopoverBehaviorTransient は、ポップオーバーがウィンドウにある場合は正常に機能しますが、ステータス バーにある場合は機能しません。

このような動作を自分で実装するにはどうすればよいですか?

4

2 に答える 2

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 の上にフロートし、フルスクリーン ウィンドウへの切り替えなどを処理するカスタム ウィンドウを実装する必要がありました。

于 2012-02-12T21:21:03.330 に答える
9

私が使用するアプローチは、2 つの個別の IBAction を使用する代わりに、すべてを 1 つのメソッドに結合することを除いて、上記の回答に似ています。

まず、次のプロパティを宣言します

@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 に設定する必要があることに注意してください。

于 2014-04-12T13:55:24.120 に答える