2014-05-11 15 views
6

Nell'ultimo aggiornamento snapchat, quando si "scorre a destra per i messaggi" la barra di stato passa da nero a bianco in una sorta di sfumatura.Aggiornamento barra di aggiornamento Snapchat Aggiornamento iOS7

http://imgur.com/osJI20u

Come stanno facendo questo senza usare API private, o stanno usando API private?

Quello che ho guardato in:

A prima vista, ho pensato che sono solo facendo quello che fanno tutti, (come rdio attualmente fa) dalla schermata di cattura l'intero schermo, e quindi modificando/animatore quello screenshot.

Ma ... non puoi accedere o animare UIImage da quel metodo di cattura dello schermo, quindi sebbene tu possa spostare/ritagliare quello screenshot, non puoi cambiare il suo aspetto.

Quindi ... l'ho provato e quando la barra di stato si trova in quello stato (mezzo nero/metà bianco), è ancora LIVE come nel suo non uno screenshot e risponde alle variazioni di carica/cambiamenti di segnale ecc. , per quanto posso dire questo è impossibile senza usare un'API privata.

+0

Forse stanno ripetutamente schermando la barra di stato e modificando ripetutamente i cappucci durante la transizione. O forse stanno rilevando i cambiamenti di batteria/tempo/segnale, quindi la limitazione dello schermo solo quando queste cose cambiano. –

+2

Chiaramente c'è una magia profonda a piedi. – CrimsonChris

risposta

15

Questo mi ha incuriosito quindi ho giocato un po 'con l'app e ho esaminato la gerarchia delle viste dell'app utilizzando Spark Inspector su un dispositivo jailbroken e ho trovato alcune cose.

Non si è certi di non utilizzare uno screenshot. La barra di stato sul lato in cui stai navigando VIA è un'istantanea e non cambia. Puoi vederlo facilmente quando passa un minuto, la nuova barra di stato per la vista in cui stai effettuando la transizione sarà cambiata perché è reale ma quella vecchia non lo sarà perché è un'istantanea. Ciò rende l'illusione facile da elaborare.

Ecco che cosa sta accadendo a un livello elevato:

  1. Quando si inizia la transizione, l'applicazione prende un'istantanea della barra di stato (molto probabilmente è in realtà prendendo un'istantanea dell'intera UIScreen e semplicemente ritagliando la barra di stato da esso) nel suo stato corrente e allega una finestra contenente quell'istantanea nella parte superiore della vista nella transizione, ancorata alla posizione di transizione finale e mascherata dalla vista del controller di visualizzazione "da". Questa finestra sembra avere un windowLevel sopra UIWindowLevelStatusBar quindi è in grado di coprire la barra di stato reale.

  2. Quindi, il controller di visualizzazione "a" acquisisce la barra di stato attuale e la modifica nello stato "contenuto di luce". Ciò presenta l'illusione intelligente che una singola barra di stato cambia colore con il bordo di transizione, ma la barra di stato reale è in realtà sempre posizionata sotto la finestra dell'istantanea e sarebbe effettivamente visibile immediatamente quando le transizioni iniziano se non fosse per la finestra dell'istantanea seduta sopra.

+1

Hai ragione, la vista da cui proviene la cattura dello schermo e la vista che sta utilizzando una barra di stato reale, è quello che mi ha preso in giro. Cheeky con la nuova finestra in alto. Immagino che Apple possa solo scoraggiarlo, ma permetterlo comunque! –

+0

Hey Dima, bella risposta. Potresti dare un'occhiata a questa domanda http://stackoverflow.com/questions/31378595/same-dynamic-status-bar-as-is-in-new-apple-music-app.Apparentemente la nuova app musicale fa proprio questo con la barra di stato, ma è sicuramente in diretta su entrambe le estremità. (non si usa un'istantanea come lo snapchat). – Segev

+0

Grazie per il commento. Sembra che sia molto probabilmente un'API privata, ma terrò d'occhio anche quella domanda. Hanno avuto una funzionalità simile nella sovrapposizione del centro di notifica verso il basso (dove la barra di stato si abbassa dinamicamente con la vista) per almeno un anno, quindi hanno sicuramente qualche asso nella manica che non ci è stato ancora fornito. – Dima

1

Compilare ciò che Dima ha risposto, ho pensato che un'implementazione di base per far iniziare le persone potesse essere d'aiuto. Come ha detto Dima, non sta spostando la barra di stato, ma spostando un'immagine della barra di stato.

Diniego: Ho YOLO'd questa implementazione così faccio garanzie su se funzionerà fuori dalla scatola

Partendo iOS7 è possibile scattare una fotografia con

UIView *screen = [[UIScreen mainScreen] snapshotViewAfterScreenUpdates:NO]; 

Così in pratica la barra di stato viene ritagliata dall'immagine e aggiunta a UIWindow con uno sopra UIWindowStatusLevelBar in modo da poterlo vedere sulla barra di stato reale. Qualcosa di simile:

UIWindow *statusBarWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 
statusBarWindow.windowLevel = UIWindowLevelStatusBar + 1; // higher 
statusBarWindow.hidden = NO; // fun fact you don't have to add a UIWindow to anything, just setting hidden = NO should display it 
statusBarWindow.backgroundColor = [UIColor clearColor]; // since visible, make it clear until we actually add the screen shot to it so as to not block anything 

... 

// The view that will hold the screen shot 
// Later, I think we're going to need to play with contentInsets to make the view look like its staying still, so we're making it a UIScrollView in case 
UIScrollView *statusBarView = [[UIScrollView alloc] initWithFrame:[UIApplication sharedApplication].statusBarFrame]; 
statusBarView.clipsToBounds = YES; 

// Now we add the screen shot we took to this status bar view 
[scrollingStatusBarView addSubview:statusBarView]; 
[statusBarView addSubview:screen]; // screen is the UIScrollView from previous code block (the screen shot) 

// Now add this statusBarView with the image to the window we created 
[statusBarWindow addSubview:statusBarView]; 

Ora il resto in realtà dipende da ciò che la vostra applicazione sta cercando come, ma da qui si ha realmente solo bisogno di gestire lo spostamento della vista o con una padella, o qualsiasi azione sta causando la nuova vista di entrare attraverso il lato.


Quando strisciata inizia, configurare la nuova barra di stato (quello sotto) con qualsiasi stile, fondo, qualsiasi cosa:

[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent animated:NO]; 
// anything else you might feel like doing 

Ora abbiamo qualcosa di interessante sta succedendo qui. Man mano che la transizione si sposta, dovrai utilizzare l'importo scorretto per "ritagliare" quell'offset dall'offset dello statusBarView. Lo statusBarView.frame dovrà iniziare con x = offset oppure verrà mostrato sulla barra di stato attuale (poiché la finestra è più in alto), ma se non si modifica il contentInsets, l'immagine scorrerà con la transizione. Quindi, per creare l'illusione, dovrai spingere l'origine verso destra mentre aumenti il ​​contenuto sinistro della stessa quantità in modo che sembri trovarsi nella stessa posizione.

Così dentro qualsiasi metodo sta gestendo l'azione di scorrimento:

Nota: Questo sarà fortemente dipenderà realizzazione personale e probabilmente prendere qualche sperimentazione

// if you're using an animation to handle the transition you can match up this change in x position with the animation 

// if you're doing via pan gesture you could try something like: 
CGFloat offset = self.viewThatIsScrolling.contentOffset.x; // may be negative depending on direction that is being swiped 

if (midTransition) { // you can use the offset value here to check 
    // NOTE: again, will depend on which direction this animation is happening in. I'll assume a new view coming in from left (so swiping right) 
    statusBarView.frame = CGRectMake(offset, 0, self.statusBarView.frame.width, 20.0f); // move the origin over to the right 
    statusBarView.contentInsets = UIEdgeInsetsMake(0, offset, 0, 0); // make the picture start 'offset' pixels to the left so it'll look like it hasn't moved 

} 

(Nota a margine: è anche possibile prova ad usare una trasformazione invece di impostare esplicitamente il frame: statusBarView.transform = CGAffineTransformMakeTranslation(offset -previousOffsetAmount, 0);. Io uso il previousOffsetAmount lì perché vuoi che si muova da qualsiasi nuova quantità in modo che possa corrispondere.Questo dovrà essere rintracciato in qualche modo se vai questo percorso)

E infine una volta che il 'scorrimento' è fatto, non dimenticate di rimuovere la schermata dalla finestra completamente:

// if continuing from before: 
if (midTransition) { 
    ... 
} else { // the view has been slid completely 
    [statusBarView removeFromSuperview]; 
    statusBarView = nil; 
    // I'm keeping the UIWindow where it is for now so it doesn't have to be recreated and because it has a clear background anyways 
} 

// if this is being done via animation the above can be called the animation finishes 

potrei davvero essere interessato a cercare di ottenere questo al lavoro, così aggiornerà se così.