2012-01-29 12 views
17

Estoy creando una aplicación que se encuentra en la barra de estado. Cuando se hace clic en el elemento de estado, aparece NSPopover.Transitorio de PoEmpo NSPopover en la barra de estado

Parece que este:

enter image description here

aquí está el problema: Quiero que sea "transitoria", es decir, si hago clic en cualquier lugar fuera de la popover, se va a cerrar. Y aunque NSPopoverBehaviorTransient funciona bien cuando popover está en una ventana, no funciona cuando está en la barra de estado.

¿Cómo puedo implementar tal comportamiento yo mismo?

Respuesta

28

Resultó ser fácil:

- (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) 
} 

Lo que no fue fácil, sin embargo, es que hay problemas desagradables con tener un pop popover de NSStatusItem (que no se comportó como se desea cuando la misión Se invocó el control o se cambió el espacio a una ventana de pantalla completa). Tuve que implementar una ventana personalizada que siempre flota sobre NSStatusItem y trata de cambiar a una ventana de pantalla completa, etc. Parecía fácil, pero claramente los elementos de estado no estaban diseñados para algo así;)

+5

Para un comportamiento consistente con el de los elementos de estado del sistema: 'addGlobalMonitorForEventsMatchingMask: NSLeftMouseDownMask | NSRightMouseDownMask' - para que los clics derechos también cierren el popover. – inket

7

El enfoque que Yo uso es similar a la respuesta anterior, excepto que tengo todo combinado en un método en lugar de utilizar dos IBActions por separado.

En primer lugar, declaro las siguientes propiedades

@property (strong, nonatomic) NSStatusItem *statusItem; 
@property (strong, nonatomic) NSEvent *popoverTransiencyMonitor; 
@property (weak, nonatomic) IBOutlet NSPopover *popover; 
@property (weak, nonatomic) IBOutlet NSView *popoverView; 

después en awakeFromNib He definido el elemento de la barra de estado

- (void)awakeFromNib { 

    self.statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength]; 

    self.statusItem.title = @"Title"; 
    self.statusItem.highlightMode = YES; 
    self.statusItem.action = @selector(itemClicked:); 
} 

seguido por el método que se llama cuando se hace clic en el elemento de la barra de estado

- (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]; 
     }]; 
    } 
} 

que hace que aparezca el popover y también se cierra cuando el usuario hace clic fuera de la vista.

Tenga en cuenta que en Interface Builder debe establecer el comportamiento del popover en Transient para que el popover se cierre cuando el usuario haga clic en el elemento de estado.

Cuestiones relacionadas