2011-10-07 16 views
9

Nella mia app per iPad ho un controller di visualizzazione con una vista piccola tabella. Quando si tocca la vista tabella, si apre un controller di visualizzazione modale che è una versione più grande e più raffinata della vista tabella piccola. Vorrei creare un'animazione da un'immagine pre-renderizzata del controller della vista grande ridimensionando l'immagine in modo che fosse la dimensione della vista del piccolo tavolo e ingrandirla a schermo intero, quindi sostituire l'immagine con la vista "reale" controller.Come si presenta un UIViewController con lo zoom?

Qualcosa di simile:

LargeViewController* lvc = [[LargeViewController alloc] init]; 
[self presentModalViewController:lvc byZoomingFromRect:CGRectMake(50,50,200,300)]; 

So che è possibile produrre un'immagine da una vista:

- (UIImage *) imageWithView:(UIView *)view 
{ 
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, [[UIScreen mainScreen] scale]); 
    [view.layer renderInContext:UIGraphicsGetCurrentContext()]; 
    UIImage * img = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 
    return img; 
} 

Ma come faccio a rendere la vista del controller sorteggio stesso (fuori campo) così posso prendere è visualizzare e ridimensionare l'immagine in un'animazione per riempire lo schermo?

Grazie in anticipo.

risposta

3

Suppongo che tu voglia creare la tua animazione personale. Il mese scorso ho giocato con qualcosa del genere. La mia soluzione era l'aggiunta di una vista personalizzata (forse presa da un controller di visualizzazione) alla vista corrente come una sovrapposizione. Funziona anche con i livelli.

Prima di scaricare l'immagine dal tuo controller di visualizzazione "futuro" o "presente", come hai fatto nell'esempio di codice sopra riportato. Normalmente il contenuto dei controller di visualizzazione dovrebbe essere disponibile durante il rendering nel contesto.

Ora hai l'immagine. La manipolazione dell'immagine deve essere fatta da te.

Aggiungere l'immagine a UIImageView. Questo ImageView può essere aggiunto come subview o layer. Ora hai un livello in cui puoi disegnare liberamente sopra la tua attuale interfaccia utente. A volte devi spostare il livello o la vista intorno, in modo da sovrapporre perfettamente la tua vista. Questo dipende dall'impostazione della visualizzazione. Se hai a che fare con Tableviews, aggiungere una sottoview non è così facile. Quindi meglio usare il livello.

Al termine del lavoro, presentare il nuovo controller di visualizzazione senza animazione, in modo che venga visualizzato immediatamente.

Rimuovere il livello o la vista dalla vista genitore al termine del lavoro e pulire.

Questo sembra complicato, ma una volta che hai fatto questo hai un modello per questo. In "WWDC 2011, Session 309 Presentazione di Interface Builder Storyboarding" Apple ha introdotto 'segues personalizzati', in cui troverai un meccanismo per esattamente ciò che vuoi fare. Il seguente codice è un taglio fuori da un progetto precedente ed è in qualche modo disordinato e deve essere ripulito. Ma per mostrare il principio questo dovrebbe funzionare:

-(void) animate { 

     static LargeViewController* lvc = [[LargeViewController alloc] init]; 

     UIGraphicsBeginImageContextWithOptions(self.bounds.size, view.opaque, [[UIScreen mainScreen] scale]); 
    [lvc.view.layer renderInContext:UIGraphicsGetCurrentContext()]; 

     // Create a ImageView to display your "zoomed" image 
     static UIImageView* displayView = [[UIImageView alloc] initWithFrame:self.view.frame]; 
     static UIImage * img = UIGraphicsGetImageFromCurrentImageContext(); 
     UIGraphicsEndImageContext(); 

     // Add your image to the view 
     displayView.image = img; 

     // insert the view above your actual view, adjust coordinates in the 
     // frame property of displayView if overlay is misaligned 
     [[self.view] addSubview:displayView]; 

     // alternatively you can use the layer 
     // [self.view.layer addSublayer:displayView.layer]; 

     // draw the imageView 
     [displayView setNeedsDisplay]; 

     // do something in background. You may create your own 
     // construction, i.e. using a timer 
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 

      NSDate *now = [NSDate date]; 
      NSTimeInterval animationDuration = 3.; 
      NSTimeInterval t = -[now timeIntervalSinceNow]; 
      while (t < animationDuration) { 

       t = -[now timeIntervalSinceNow]; 

       // Do some animation here, by manipulation the image 
       // or the displayView 

       // <calculate animation>, do something with img 
       // you have exact timing information in t, 
       // so you can set the scalefactor derived from t 
       // You must not use an UIImage view. You can create your own view 
       // and do sth. in draw rect. Do whatever you want, 
       // the results will appear 
       // in the view if you added a subview 
       // or in a layer if you are using the layer 

       dispatch_sync(dispatch_get_main_queue(), ^{ 

        // display the result 
        displayView.image = img; 
        [displayView setNeedsDisplay]; 
       }); 
      } 
     }); 

     // now the animation is done, present the real view controller 
     [self presentModalViewController:lvc animated:NO]; 

     // and clean up here 
} 
+0

Finalmente avuto il tempo di testare i tuoi suggerimenti, molto dettagliati. Funziona come un fascino! Grazie mille per il tuo contributo! Inoltre, anche la sessione 309 del WWDC 2011 con sequenze personalizzate avrebbe funzionato alla grande. –

0

Forse si potrebbe usare qualcosa come

CGAffineTransform tr = CGAffineTransformScale(lvc.view.transform, 0.5, 0.5); 

per incorporare una versione ridotta della vista nel vostro controller della vista genitore, allora presenti modale LVC e ripristinare scala quando l'utente tocca la vista.

0

UIKit si prende cura di gran parte di questo per voi. Anche se la soluzione di jbat100 potrebbe essere fatta funzionare, dovresti essere in grado di farlo semplicemente impostando il fotogramma iniziale di lvc sul rect più piccolo a cui vuoi iniziare e poi quando imposti il ​​fotogramma anche a dimensione intera, l'animazione implicita per cambiare la cornice gestirai l'animazione dello zoom per te. Ogni UIView ha un CALayer in cui viene disegnato il suo contenuto e quel livello ha diverse impostazioni di animazioni implicite per le modifiche animate a determinate proprietà come le proprietà del frame o della posizione. Ecco il mio pugnalata testata a lui:

 . 
     . 
    lvc.view.frame = CGRectMake(50,50,200,300); 
    [self performSelector:@selector(setFrameToFullScreen) withObject:nil afterDelay:0]; 

} 

- (void)setFrameToFullScreen { 
    lcv.view.frame = [UIScreen mainScreen].bounds; 
} 

La chiamata performSelector:withObject:afterDelay causerà setFrameToFullScreen ad essere chiamato sul prossimo ciclo di ciclo di esecuzione. Se non si fa qualcosa del genere, verrà utilizzato solo il fotogramma finale e il sistema non riconoscerà la modifica nel fotogramma e applicherà la sua animazione implicita al livello di viste.

+0

Il problema è che un controller di visualizzazione non ha una proprietà frame poiché non è una classe di visualizzazione. L'unico modo che conosco per visualizzare un controller di visualizzazione consiste nell'utilizzare il metodo presentModalViewController: animated: e tale metodo imposta l'animazione stessa. –

+0

Vostro diritto! il controller della vista non ha una cornice, ma la sua vista lo fa. Ho modificato il codice sopra per riflettere questo. – Logachu

Problemi correlati