2011-01-03 17 views
17

Ho visto alcuni materiali sul web, ma ancora non riesco a arrivare dove voglio. Ho bisogno di animare la mia vista verso il basso, aumentando l'altezza.come animare durante il ridimensionamento UIView

Ecco il mio codice finora. Quello che sta succedendo qui è che invece di ridimensionare la mia vista, è solo cambiando la sua posizione un po 'su. Se cambio la proprty invece di "bounds.size" essere "transform.scale.y", è un po 'meglio, solo che questa volta si espande la vista sia su e giù, non solo verso il basso.

Un'altra cosa che io non sono di: sono queste le chiavi solo proprietà CALayer? dove posso trovare un elenco di queste chiavi?

Vorrei davvero apprezzare aiuto qui. Grazie!

int x = self.btnHead.frame.origin.x; 
int y = self.btnHead.frame.origin.y; 
int height = self.btnHead.frame.size.height; 
int width = self.btnHead.frame.size.width; 


CABasicAnimation *resizeAnimation = [CABasicAnimation animationWithKeyPath:@"bounds.size"]; 
[resizeAnimation setToValue:[NSValue valueWithCGSize:CGSizeMake(width,height+50)]]; 
resizeAnimation.fillMode = kCAFillModeForwards; 
resizeAnimation.removedOnCompletion = NO; 

CAAnimationGroup *animationGroup = [CAAnimationGroup animation]; 
animationGroup.animations = [NSArray arrayWithObjects:resizeAnimation,nil]; 
animationGroup.removedOnCompletion = NO; 
animationGroup.fillMode = kCAFillModeForwards; 
animationGroup.removedOnCompletion=NO; 
animationGroup.duration = 0.1; 

[self.btnHead.layer addAnimation:animationGroup forKey:@"animations"]; 

Edit: postare il mio primo codice come richiesto - Questo sarà solo cambiare la mia dimensione di visualizzazione, ma non animerà, non importa la durata io entro.

int x = self.btnHead.frame.origin.x; 
    int y = self.btnHead.frame.origin.y; 
    int height = self.btnHead.frame.size.height; 
    int width = self.btnHead.frame.size.width; 


    [UIView beginAnimations:nil context:nil]; 
    [UIView setAnimationDuration:10]; 
    CGRect rect = CGRectMake(x,y,width ,height+BUTTON_HEIGH*2); 

    self.btnHead.frame = rect; 

    [UIView commitAnimations]; 

risposta

10
btnHead.clipsToBounds=YES 

Risolto il problema. Non so esattamente perché.

+0

Suppongo che l'impostazione 'btnHead.clipsToBounds = YES' impone efficacemente un'impostazione di ridisegno come 'btnHead.contentMode = UIViewContentModeRedraw'. Tuttavia, non fa menzione di ciò nella documentazione. Questo probabilmente accade perché è molto probabile che cambiando i 'limiti' di una vista con ritaglio attivato mostrerà parti della sua gerarchia di viste che non erano visibili prima. Ecco come funzionano le visualizzazioni di scorrimento. –

9

Non puoi semplicemente cambiare la cornice all'interno di un blocco di animazione UIView. Sembra che CABasicAnimation non sia necessario in questo caso.

 
[UIView beginAnimations:@"resize_animation" context:NULL]; 
// set your duration. a long duration is better to debug 
// 0.1 is really short to understand what is going wrong 
[UIView setAnimationDuration:2]; 

btnHead.frame = newFrame; 

[UIView commitAnimations]; 
+0

Non ami semplicemente la semplicità? – Jake

+0

No! Ho provato quella prima cosa. non funziona cambia la dimensione del fotogramma ma non si anima. – Idan

+0

Si prega di inviare il codice. Potrebbe esserci qualche altro problema. – taskinoor

53

Animare la proprietà frame può essere problematico, ma dovrebbe funzionare correttamente fino a quando il transform è l'identità (cioè, non scelto). Ho appena provato il seguente codice, e ha funzionato come previsto:

[UIView animateWithDuration:.1f animations:^{ 
    CGRect theFrame = myView.frame; 
    theFrame.size.height += 50.f; 
    myView.frame = theFrame; 
}]; 

Ancora una volta, questo non funzionerà come previsto se hai cambiato la proprietà transform in qualsiasi momento. Per una versione più a prova di proiettile di questa animazione, è necessario animare la proprietà bounds come si è tentato con Core Animation. Non hai ancora bisogno di entrare in Core Animation, però.

La cosa importante da capire qui è la relazione tra le proprietà bounds e center. Tutte le trasformazioni affini (tradurre, ridimensionare o ruotare) necessitano di un punto di riferimento su cui eseguire la trasformazione. Nel caso di un UIView è il punto center. CALayer consente di spostare il punto di riferimento in tutto tramite la proprietà anchorPoint, ma non hanno bisogno di preoccuparsi che in questo caso.

Il motivo per cui la vista viene ridimensionata in entrambe le direzioni è che l'operazione di ridimensionamento si verifica attorno allo center. La cosa più semplice da fare allora è spostare lo y di metà dell'altezza delta. Come questo:

myView.contentMode = UIViewContentModeRedraw; 
[UIView animateWithDuration:.4f animations:^{ 
    CGRect theBounds = myView.bounds; 
    CGPoint theCenter = myView.center; 
    theBounds.size.height += 50.f; 
    theCenter.y += 25.f; 
    myView.bounds = theBounds; 
    myView.center = theCenter; 
}]; 

La considerazione finale sta costringendo la vista per ridisegnare quando i bounds modifiche. Per motivi di prestazioni, la vista non verrà ridisegnata quando si modifica il suo bounds. Tuttavia, viene ridisegnato quando si modifica la proprietà frame (ancora un'altra peculiarità della proprietà frame). Per forzare un nuovo aggiornamento sulla modifica bounds, è necessario impostare contentMode come ho fatto nella prima riga del frammento precedente. Probabilmente vorrai rimetterlo al termine dell'animazione, ma dipende da te. Questo è anche il motivo per cui la versione Core Animation cambia solo la posizione e non la dimensione.Hai bisogno di questa riga nel codice da qualche parte prima di eseguire l'animazione:

self.btnHead.layer.needsDisplayOnBoundsChange = YES; 

Spero che tutto abbia un senso. Le proprietà frame, bounds e center all'inizio possono essere un po 'confuse.

+0

In primo luogo, grazie per una risposta davvero grande. Ora per i tuoi punti, perché non è necessario cambiare il punto centrale quando si modifica il fotogramma, mentre è necessario quando si modificano i limiti? Comunque, è risultato che ha iniziato ad animare dopo aver messo btnHead.clipsToBounds = YES .... Non so perché. – Idan

+4

Il 'frame' è una proprietà di convenienza (per rendere più semplici le viste) che descrive il rettangolo della vista nello spazio delle coordinate del genitore. Il valore 'frame' non viene mai memorizzato. È calcolato dai 'limiti' e' centro'. Quindi quando cambi il 'frame', stai effettivamente cambiando i' bounds' e 'center'. I 'limiti' descrivono il rettangolo di delimitazione della vista nel proprio spazio di coordinate (ecco perché la sua origine è di solito {0, 0}), e il' centro' descrive la posizione della vista nello spazio delle coordinate del genitore. Quindi, i due esempi di codice in realtà fanno esattamente la stessa cosa. –

+0

Salve, Ciò significa che di solito non dovrei toccare bounds.origin, ma solo il bounds.size e center quando voglio cambiare la sua posizione sullo schermo (è (x, y))? Immagino che cambiare la cornice sia molto più facile comunque. – Idan

2

clipsToBounds è la soluzione.

Spiegazione: ClipToBounds è una proprietà che specifica se subviews devono essere ritagliate o meno. Pertanto, se una sottoview è più grande della sua superview, verrà ritagliata se si imposta "superview.clipToBounds=YES". Nel caso di questo post, il superview è stato ridimensionato ma non c'era alcuna differenza visibile per l'utente, poiché le subviste sono state tracciate anche se si trovavano fuori dal frame.

È un po 'complicato, perché non esiste un collegamento visibile con l'animazione, ma è per questo che questa proprietà fa la differenza.

Problemi correlati