2009-05-18 8 views
11

Sto provando a passare da un UIView a un altro, quando l'utente ruota il dispositivo. Questo, di per sé, non è difficile. Tuttavia, poiché visualizzo contenuti completamente diversi dopo la rotazione, l'animazione predefinita fornita da UIKit (ruotando la vista attualmente visualizzata) è inappropriata concettualmente.Come catturare lo screenshot della vista corrente e riutilizzarlo nel codice? (iPhone SDK)

Semplicemente disabilitando l'animazione e scambiando le viste, è improvvisamente tollerabile, ma è molto al di sotto dello smalto che sto costruendo nel resto dell'app. Quello che preferirei fare è questo:

Quando si chiama "Autotopotale": "Mi piace", desidero catturare un'istantanea della vista opaca, uno screenshot se lo si desidera, della vista utente prima della rotazione. Quindi, dopo che la rotazione è completata e il sistema ha applicato la vista trasforma ecc., Posso mostrare la vista dell'istantanea che ho salvato e animare una transizione della mia scelta alla mia nuova vista. Dopo che è stato completato, posso rilasciare la mia istantanea e andare avanti.

C'è un modo per farlo che non sia costoso?

L'unica altra opzione che posso pensare è di restituire NO su tutti gli orientamenti diversi da quello predefinito, quindi reagire applicando le mie animazioni e le mie trasformazioni. Preferirei utilizzare il sistema per farlo, tuttavia, poiché ritengo che farlo probabilmente potrebbe causare un comportamento "non definito" della tastiera nella visualizzazione ruotata manualmente, ecc.

Pensieri?

+0

Vorrei sottolineare che ora ho tentato quello che ho detto come la seconda opzione: reagire da manualmente applicando le mie viste e le trasformazioni dopo aver restituito NO ... e la tastiera appare effettivamente nell'orientamento sbagliato. Sono in perdita per correggere questo comportamento, se dovessi procedere in questa direzione. –

risposta

1

Posso garantire che [finestra drawRect:] non funzionerà. La maggior parte delle viste non implementa drawRect: e certamente non è ricorsivo come nel mac.

drawInContext: è anche molto simulato in modo similare, in quanto chiede fondamentalmente allo strato di disegnare se stesso, non i suoi sottolivelli in modo ricorsivo. "L'implementazione di default non fa nulla." dice tutto.

ho l'attuazione del presente per l'applicazione Clif Bar Save Our Neve in App Store nel modo seguente:

  • Walk the gerarchia dei livelli in modo ricorsivo, ottenendo il contenuto da ogni strato. Se ha l'odore di un'immagine, usa i metodi di CGContext per disegnarlo nel tuo contesto.
  • Mentre si cammina, fare in modo di applicare le trasformazioni/posizioni di ogni livello, come si chiamano in modo ricorsivo

Sì, una piuttosto grande dolore nel culo. Ma sì, funziona abbastanza bene e ottenuto da Apple :).

4

Su Mac questo è così facile ... hai solo bisogno di -bitmapImageRepForCachingDisplayInRect:, ma naturalmente iPhone non ha nulla del genere.

Penso che vorrei attaccare questo impostando un contesto grafico e chiamando [window drawRect:...] su di esso per catturare l'immagine corrente dello schermo. Questo è un po 'fuori dalle specifiche, perché in realtà non dovresti chiamare il numero -drawRect: da solo. Sarei un po 'nervoso per gli effetti collaterali su questo, ma potrebbe andare bene. Se si tratta di una visualizzazione a schermo intero che controlli, puoi ovviamente sollevare il codice di disegno da -drawRect: in modo da non chiamarlo direttamente.

Un approccio simile sarebbe quello di utilizzare CALayer -drawInContext: dell'attuale -presentationLayer. Potrebbe essere leggermente più "in specifica" dal momento che è legale passare il proprio contesto. Ma non so se saresti in grado di ottenere correttamente tutte le viste secondarie. Potrebbe dipendere dalla natura della tua UIWindow.

In ogni caso, ottima domanda. Forse qualcuno ha una soluzione più intelligente, ma questo è il modo in cui lo attaccherei.

EDIT: Grazie a Rob Terrell, e la sua intelligente UIApplication+TVOut.m, mi è stato introdotto al metodo UIGetScreenImage privata(), che restituisce un CGImageRef. Se sei disposto a seguire metodi privati, questa è una buona opzione per te. Dato il suo nome e la sua funzionalità, mi sembra abbastanza stabile e sembra improbabile che violi l'intento di Apple. Ho anche fatto una bella discussione su Air Source. Leggi i commenti per diversi link.

+0

Se desideri pubblicare su App Store, utilizzando UIGetScreenImage() la tua app verrà respinta. –

21
- (UIImage *)captureView:(UIView *)view { 
    CGRect screenRect = [[UIScreen mainScreen] bounds]; 

    UIGraphicsBeginImageContext(screenRect.size); 

    CGContextRef ctx = UIGraphicsGetCurrentContext(); 
    [[UIColor blackColor] set]; 
    CGContextFillRect(ctx, screenRect); 

    [view.layer renderInContext:ctx]; 

    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); 

    UIGraphicsEndImageContext(); 

    return newImage; 
} 

Trovato questo qui:

http://discussions.apple.com/thread.jspa?messageID=8358740

+0

ottima scoperta, funziona perfettamente. – Rog

+1

C'è un grosso problema con questo approccio: 'UIGraphicsGetImageFromCurrentImageContext()' perde memoria (l'UIImage che crea non è mai disposto correttamente), almeno nelle vecchie versioni del sistema operativo (5.0 sembra non avere più questo problema). – MusiGenesis

12

Questo codice ha funzionato per me

- (UIImage *)captureScreenInRect:(CGRect)captureFrame { 
    CALayer *layer; 
    layer = self.view.layer; 
    UIGraphicsBeginImageContext(self.view.bounds.size); 
    CGContextClipToRect (UIGraphicsGetCurrentContext(),captureFrame); 
    [layer renderInContext:UIGraphicsGetCurrentContext()]; 
    UIImage *screenImage = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 
    return screenImage; 
} 
+0

Sto affrontando un problema con questo. Sto facendo il rendering di tratti su uno sfondo chiaro e non appena salvi, aggiunge uno sfondo nero all'immagine da qualche parte. – manishnath

+1

Il tuo codice funziona perfettamente! – user523234

+1

Grazie amico funziona – Hiren

Problemi correlati