2010-05-20 9 views
30

Ho una vista eccellente, che ha 2 sottoview. Queste sottoview sono sovrapposte.Come faccio a spostare NSView nella parte anteriore di tutte le NSViews

Ogni volta che scelgo una vista da un menu, la vista corrispondente dovrebbe diventare la vista frontale e gestire le azioni. cioè, dovrebbe essere la vista secondaria più frontale.

acceptsFirstResponder si dimette tutti funzionano bene. Ma gli eventi mouse-down vengono inviati alla vista secondaria più in alto che è stata impostata.

saluti, Dhana

+0

attenzione che: "Nota: Per motivi di prestazioni, di cacao non applica clipping tra vista di pari livello ..." Ed ancora! "Il cacao non ... garantisce l'invalidazione corretta e il comportamento di disegno quando le viste di pari livello si sovrappongono." Come si dice nel manuale:" Se vuoi che una vista sia disegnata di fronte a un'altra vista, devi rendere la vista frontale una sottoview (o discendente) della vista posteriore. " (dalla programmazione View Guida nel documento OSX) – Fattie

risposta

35

Ecco un altro modo per raggiungere questo obiettivo che è un po 'più chiara e concisa:

[viewToBeMadeForemost removeFromSuperview]; 
[self addSubview:viewToBeMadeForemost positioned:NSWindowAbove relativeTo:nil]; 

Per la documentazione per questo metodo, quando si utilizza relativeTo:nil la vista viene aggiunta sopra (o sotto, con NSWindowBelow) tutti i suoi fratelli.

+3

C'è un problema con l'approccio di cui sopra: in primo luogo, quando si invia ** removeFromSuperview ** a una vista, questa viene rilasciata Quindi è necessario prima mantenere la vista, quindi bilanciare l'originale con una In secondo luogo, si ha il sovraccarico di rimuovere e aggiungere la vista alla gerarchia (che può essere costosa a seconda della complessità della vista gerarchica hy). C'è un altro modo per farlo, che evita di dover rimuovere e aggiungere viste dalla gerarchia della vista usando la funzione di ordinamento subview integrata di NSView. Vedi sotto. – Dalmazio

+0

Penso che le due righe di codice siano ancora nello stesso ciclo di eventi, quindi viewToBeMadeForemost non verrà rilasciato prima della seconda riga. –

+0

@LiFumin, che non è corretto. Si presume che removeFromSuperview autorizzi automaticamente la vista o che l'altro codice sia automaticamente rilasciato. Dal documento per -removeFromSuperview: "Viene anche rilasciata la vista, se si prevede di riutilizzarla, assicurarsi di conservarla prima di inviare questo messaggio e di rilasciarlo come appropriato quando lo si aggiunge come sottoview di un altro NSView." Dalmazio è corretto, la vista deve essere mantenuta. Questa soluzione ha anche problemi relativi alla rottura dei vincoli, ecc., Immagino. Non dovrebbe essere la risposta accettata. – bhaller

1

seguito dato codice dovrebbe funzionare bene ..

NSMutableArray *subvies = [NSMutableArray arrayWithArray:[self subviews]];//Get all subviews.. 

    [viewToBeMadeForemost retain]; //Retain the view to be made top view.. 

    [subvies removeObject:viewToBeMadeForemost];//remove it from array 

    [subvies addObject:viewToBeMadeForemost];//add as last item 

    [self setSubviews:subvies];//set the new array.. 
+0

A meno che non si usi ARC ... – geowar

+0

Questa dovrebbe essere la risposta accettata, poiché è più vicina all'essere corretta rispetto agli altri, tuttavia, si noti che dovrebbe fare una [viewToBeMadeForemost release]; alla fine, altrimenti c'è una perdita – bhaller

11

Un altro modo è utilizzare il metodo sortSubviewsUsingFunction: context: di NSView per riordinare una raccolta di viste di pari livello a proprio piacimento. Ad esempio, definire la funzione di confronto:

static NSComparisonResult myCustomViewAboveSiblingViewsComparator(NSView * view1, NSView * view2, void * context) 
{  
    if ([view1 isKindOfClass:[MyCustomView class]])  
     return NSOrderedDescending;  
    else if ([view2 isKindOfClass:[MyCustomView class]])  
     return NSOrderedAscending;  

    return NSOrderedSame; 
} 

Poi, quando si vuole garantire la visualizzazione personalizzata rimane al di sopra tutte le viste di pari livello, inviare questo messaggio a superview di visualizzazione personalizzata:

[[myCustomView superview] sortSubviewsUsingFunction:myCustomViewAboveSiblingViewsComparator context:NULL]; 

In alternativa, si può sposta questo codice sul superview stesso e invia il messaggio sortSubviewsUsingFunction: context: a self invece.

+2

@ Jonathan. Questo è per UIViews che fanno parte del framework iOS. La domanda riguarda NSViews che vengono utilizzate per le app OS X. – Mathias

+0

Funziona, ma sembra rendere casuale l'ordine delle restanti sottoview, poiché il documento dice "NSOrderedSame se il loro ordine non è importante". Una soluzione che preservi l'ordinamento del resto delle visualizzazioni sarebbe molto meglio. Inoltre, l'uso di IsKindOfClass: qui è strano; la domanda non stabilisce che vengano utilizzate sottoclassi di visualizzazione personalizzata o che le sottovoci di pari livello da riordinare siano classi diverse. – bhaller

-10

Si potrebbe provare questo:

[viewToBeMadeFirst.window makeKeyAndOrderFront:nil]; 
+0

sì, questo funziona per me: [self.window makeKeyAndOrderFront: self]; –

+8

Stiamo parlando di NSView, non di NSWindow – NSAddict

4

ero in grado di farlo funzionare senza chiamare removeFromSuperView

// pop to top 
[self addSubview:viewToBeMadeForemost positioned:NSWindowAbove relativeTo:nil]; 
+0

Questo crea una nuova vista anziché utilizzare la vista esistente? – Krishnabhadra

+1

Ciò ha causato il blocco permanente dell'app. –

+0

Se funziona, è solo per caso; i documenti non forniscono alcuna garanzia circa il comportamento dell'aggiunta di una vista già aggiunta. – bhaller

1

È possibile raggiungere questo obiettivo con la sola aggiunta di nuovo la vista; non ne creerà un'altra istanza.

[self addSubview:viewToBeMadeForemost]; 

È possibile registrare il numero di sottoview prima e dopo che questa riga di codice è stata eseguita.

+1

Se funziona, è solo per caso; i documenti non forniscono alcuna garanzia circa il comportamento dell'aggiunta di una vista già aggiunta. – bhaller

0

Per spostare una vista in primo piano, deve essere posizionata come ultimo elemento nella matrice di sottoview. Ecco una soluzione Swift 3.0:

func bringChildToFrontWith(viewIdentifier: Int) { 
    var subViewArray = self.subviews // Apple docs recommend copying subViews array before operating on it, as it "can be changed at any time" 
    for ix in 0 ..< subViewArray.count { 
     if let childView = subViewArray[ix] as? MyViewSubClass { 
      if childView.myViewSubClassIdentifier == viewIdentifier { 
       let topItem = subViewArray[ix]; 
       subViewArray.remove(at: ix) 
       subViewArray.append(topItem) 
       self.contentView.subviews = subViewArray 
      } 
     } 
    } 
} 
Problemi correlati