2010-08-18 7 views
10

Ho una vista che voglio ridimensionare e tradurre in una nuova posizione animandola. Ho cercato di raggiungerlo con il seguente codice:Animazione UIVIew - Ridimensionamento + Traduzione

[UIView beginAnimations:nil context:nil]; 
[UIView setAnimationDuration:kDurationForFullScreenAnimation]; 
[[self animatingView] setFrame:finalRect]; 
[UIView commitAnimations]; 

L'effetto di questo codice è, la vista cambia prima grandezza del suo contenuto al finalRect e poi traduce nella nuova posizione. Ad esempio, la parte di ridimensionamento non è mai animata. La vista viene semplicemente trasformata nella nuova dimensione e quindi tradotta.

Questo problema è già stato discusso in diversi altri thread, ma nessuno di essi trarrà una conclusione. Tuttavia, esiste una soluzione, per utilizzare un timer e impostare il frame ogni volta nel callback del timer, ma ha un inconveniente di prestazioni.

Qual è la soluzione più appropriata a questo problema, inoltre, perché nel primo caso si verifica questo problema?

Grazie

risposta

33

L'impostazione del frame non ha né una scala né una traduzione. Stai utilizzando la terminologia sbagliata o stai usando lo strumento sbagliato per il lavoro. Scala e traduzione vengono entrambe eseguite utilizzando le trasformazioni Core Graphics Affine quando stai cercando di influenzare l'UIView (al contrario del livello che utilizza le trasformazioni Core Animation).

Per scalare una vista usare

// 2x 
[rotationView setTransform:CGAffineTransformMakeScale(2.0, 2.0)]; 

Per tradurre, utilizzare

// Move origin by 100 on both axis 
[rotationView setTransform:CGAffineTransformMakeTranslation(100.0, 100.0)]; 

Per animare questi, avvolgerli in un blocco di animazione. Se si desidera trasformare la vista con entrambi, è necessario concatenarli.

Se non si desidera affatto ridimensionamento e traslazione (trasformazioni), ciò che si intende è che si desidera modificare i limiti e la posizione della vista. Questi sono cambiati con chiamate di

[view setBounds:newRect]; 
[view setCenter:newCenter]; 

Dove newRect e nuovoCenter sono rispettivamente una CGRect e CGPoint che rappresentano la nuova posizione sullo schermo. Di nuovo, queste esigenze sono racchiuse in un blocco di animazione.

+0

Il fatto è che, se faccio in questo modo, il contenuto di vista e tutte le sue sotto-vista assumere la newRect subito . Non sono animati al nuovo frame. Come dire che hai un imageView come subView alla vista di animazione, l'immagine in imageView non viene ridimensionata gradualmente. Piuttosto, l'immagine viene prima ingrandita fino al nuovoRect e quindi i valori di scala della vista + si traducono.Tuttavia, la modifica del centro funziona nel blocco dell'animazione, ma la modifica dei limiti non funziona come previsto. –

15

Ecco un esempio con l'animazione di blocco:

CGPoint newCenter = CGPointMake(100.0,100.0); 

[UIView animateWithDuration: 1 
         delay: 0 
        options: (UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowUserInteraction) 
       animations:^{object.center = newCenter ; object.transform = CGAffineTransformScale(CGAffineTransformIdentity, 2.0, 2.0);} 
       completion:^(BOOL finished) { } 
]; 
4

provare questa soluzione:

CGAffineTransform s = CGAffineTransformMakeScale(0.5f,0.5f); 
    CGAffineTransform t = CGAffineTransformMakeTranslation(100, 0); 
    v2.transform = CGAffineTransformConcat(t,s); // not s,t 

questa operazione non è commutativa. L'ordine è l'opposto dell'ordine quando si usano le funzioni di comodità per applicare una trasformazione a un'altra.

Ed è possibile utilizzare questa operazione per: per esempio (togliere la scala):

v2.transform = 
    CGAffineTransformConcat(CGAffineTransformInvert(s), v2.transform); 
+2

Ottima risposta. Di tutte le mie ricerche, questo mi ha portato esattamente a ciò di cui avevo bisogno per far funzionare questa animazione proprio come ne ho bisogno. Sto cercando di duplicare l'animazione vista su Android quando si seleziona un campo di testo con l'etichetta si restringe più in basso e verso l'alto e verso sinistra. Solo una trasformazione di scala rimpicciolisce l'etichetta, ma verso il basso e verso destra. Era necessaria anche la trasformazione della traduzione, ma non riuscivo a trovare un modo per far funzionare entrambi. La CGAffineTransformConcat era la chiave. Grazie! – magnusMTB