2013-04-22 15 views
8

è un'altra finestra senza bordi NSWindow domanda ... Ho, trasparente, che si crea in questo modo Ecco ...NSWindow - senza bordi, trasparente finestra - sfarfallio ombra quando si anima altezza della finestra

- (id)initWithView:(NSView *)view anchorPoint:(NSPoint)anchorPoint position:(NSPoint)position distance:(CGFloat)distance { 
    if (!view) { 
    return nil; 
    } 

    NSSize size = view.intrinsicContentSize; 
    NSRect contentRect = NSMakeRect(0, 0, size.width, size.height); 

    self = [super initWithContentRect:contentRect 
          styleMask:NSBorderlessWindowMask 
          backing:NSBackingStoreBuffered 
           defer:NO]; 

    if (!self) { 
    return nil; 
    } 

    _windowView = view; 
    _anchorPoint = anchorPoint; 
    _position = position; 
    _distance = distance; 

    [self setContentView:_windowView]; 

    [self setExcludedFromWindowsMenu:YES]; 
    [self setMovableByWindowBackground:NO]; 

    [self setOpaque:NO]; 
    [self setBackgroundColor:[NSColor clearColor]]; 

    [self setHasShadow:YES]; 
    [self useOptimizedDrawing:YES]; 

    [self setReleasedWhenClosed:NO]; 

    [self setFrame:[self windowRectWithSize:contentRect.size] display:YES]; 

    [self setAnchorAttribute:NSLayoutAttributeTop forOrientation:NSLayoutConstraintOrientationVertical]; 
    [self setAnchorAttribute:NSLayoutAttributeCenterX forOrientation:NSLayoutConstraintOrientationHorizontal]; 

    [[NSNotificationCenter defaultCenter] addObserver:self 
              selector:@selector(viewFrameDidChange:) 
               name:NSViewFrameDidChangeNotification 
              object:nil]; 

    return self; 
} 

.. . e viewFrameDidChange: è definito come ...

- (void)viewFrameDidChange:(NSNotification *)note { 
    if (note.object != self.contentView) { 
    return; 
    } 

    [self display]; 
    [self setHasShadow:NO]; 
    [self setHasShadow:YES]; 
} 

... questo è l'unico modo per avere una corretta NSWindow ombra. In altre parole, ogni volta che le dimensioni della finestra, devo chiamare display, setHasShadow:NO e setHasShadow:YES altrimenti l'ombra finestra è paralizzato - non è in giro per l'intera finestra - solo una parte della finestra, ecc

Ciò lavoro fino a quando non si avvia altezza animata. Se l'altezza è animata, l'ombra viene ricalcolata e visualizzata correttamente, ma l'intera ombra della finestra & sfarfallio ed è piuttosto brutto.

Un'idea perché l'ombra è tremolante? Ho provato a sostituire display, setHasShadow:NO/YES con [self invalidateShadow], ma non funziona affatto e l'ombra viene visualizzata in modo errato.

Come si dovrebbe animare altezza della finestra con ombra in una finestra senza bordi/trasparente per evitare lo sfarfallio?

Ecco il video della ombra tremolante. http://d.pr/v/lbkQ

+1

Ho cercato in giro e questa sembra essere una domanda molto difficile a cui rispondere. Ti suggerisco di fare un supporto tecnico per gli sviluppatori con Apple (come sviluppatore ottieni 2 gratis all'anno). Sono certo che qualcuno laggiù possa risolvere questo problema per te. – sangony

+1

Ho provato a riprodurre il problema in un ambiente controllato ma non sono riuscito. Con lo stesso tipo di finestra trasparente (con graffetta trasparente) ottengo delle belle ombre non sfarfallio. Ho persino disattivato le notifiche di ridimensionamento. [Ecco il codice] (https://dl.dropboxusercontent.com/u/20258059/WindowShadows.zip). Forse non ha nulla a che fare con l'ombra stessa, ma con la vista interna che si sta ridisegnando, che ovviamente alla fine colpisce l'ombra. Dovrei ricordare che il ridimensionamento delle finestre viene fatto facendo clic sulla finestra. – aLevelOfIndirection

risposta

2

Il calcolo e il disegno dell'ombra sono un'operazione che richiede molte risorse. Quindi non ti consiglierei di invalidare e ricalcolare l'ombra ogni volta che cambia il frame. Inoltre, NSWindowDelegate ha un metodo –windowDidResize:, quindi perché utilizzare observer?

  1. Come si fa a vostra finestra ridimensionata? Forse aggiungere NSResizableWindowMask alla maschera di stile della finestra farà il trucco? Dovresti fare un tentativo.

  2. Un altro suggerimento - verificare che il contenuto della finestra ridimensiona correttamente insieme alla finestra. Hai impostato la tua finestra trasparente. Ma se non ci sono contenuti all'interno della finestra, non viene visualizzata alcuna ombra. Puoi anche provare ad aggiungere la tua vista come subview al contentView della finestra esistente invece di sostituirla.

Ho quasi la stessa impostazione nel mio progetto e posso dire che l'ombra della finestra viene visualizzata correttamente quando ridimensionate la finestra.

P.S. Una raccomandazione: non fare affidamento su "sé" nel metodo di inizializzazione dell'oggetto. Potrebbe non essere ancora completamente pronto per l'uso. Inizialmente con il minimo, regola la finestra dopo che è stata creata nel tuo controller (ad esempio, non puoi essere sicuro che setFrame: display farà quello che ti aspetti con le dimensioni corrette). Il glitch che hai potrebbe essere correlato anche a questo.

+0

Un'altra idea mi è venuta in mente ... Hai detto che senza questa invalida ombra, l'ombra della finestra è paralizzata - non è intorno all'intera finestra. Forse hai un contenuto semitrasparente in quest'area della finestra? – UJey

+1

probabilmente era un problema di temporizzazione, perché quando chiamo '[window display]; [window invalidateShadow]; 'in' -windowDidResize: ', funziona perfettamente. Ma quando stavo ascoltando le modifiche al frame di contentView e chiamavo questi due metodi lì, era tremolante come un matto. – robertvojta

+0

UJey: in altre parole, il problema è risolto. – robertvojta

2

forse è meglio spegnere ombra all'inizio dell'animazione e indietro quando si è fatto. Non cambiare questa impostazione durante l'animazione. Pensavo di averlo visto anche con altre finestre.

+0

Grazie, ma questo è l'ultimo modo che vorrei usare. Guarda Fantastical, lo stanno ridimensionando senza problemi. Oppure hanno un'ombra personalizzata ... – robertvojta