2010-08-18 17 views
10

Tengo una vista que quiero escalar y traducir a una nueva ubicación animándola. Traté de alcanzarlo con el siguiente código:Animación UIVIew - Escala + Traslación

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

El efecto de este código es, la vista primero cambia el tamaño de su contenido a la finalRect y luego lo traduce a la nueva ubicación. es decir, la parte de escalado nunca está animada. La vista simplemente se transforma al nuevo tamaño y luego se traduce.

Este problema ya se discutió en varios otros hilos, pero ninguno de ellos llega a una conclusión. Sin embargo, existe una solución para usar un temporizador y establecer el marco cada vez en la devolución de llamada del temporizador, pero tiene un inconveniente de rendimiento.

¿Cuál es la solución más adecuada para este problema, también, por qué en el primer caso se produce este problema?

Gracias

Respuesta

33

La configuración del marco no tiene escala ni una traducción. Está utilizando la terminología incorrecta o está usando la herramienta incorrecta para el trabajo. El escalado y la traducción se realizan con las transformaciones Affix de Core Graphics cuando se busca afectar a UIView (a diferencia de la capa que usa transformaciones de Core Animation).

Para escalar una vista utilice

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

para traducir, usar

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

Para animar estos, envolverlos en un bloque de animación. Si desea transformar la vista con ambos, debe concatenarlos.

Si no desea la escala y la traducción (transformaciones), quiere decir que quiere cambiar los límites y la posición de la vista. Estos se cambian con llamadas a

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

Dónde newRect y newCenter son una CGRect y CGPoint, respectivamente, que representan la nueva posición en la pantalla. Una vez más, estas necesitan envueltas en un bloque de animación.

+0

La cosa es, si lo hago de esta manera, el contenido de vista y todos sus sub-vistas asumir la newRect inmediatamente . No están animados para el nuevo marco. Como decir que tienes un imageView como subvista a la vista de animación, la imagen en imageView no se escala gradualmente. En lugar de eso, la imagen se expande primero a newRect y luego los límites de la vista se escalan + se traducen.Sin embargo, cambiar el centro funciona en el bloque de animación, pero cambiar los límites no es el esperado. –

15

Aquí se muestra un ejemplo con la animación bloque:

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

Pruebe esta solución:

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

esta operación no es conmutativa. El orden es el opuesto al orden cuando se usan funciones de conveniencia para aplicar una transformación a otra.

Y puede utilizar esta operación para: por ejemplo (quitar la Escala):

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

Gran respuesta. De toda mi búsqueda, esta me consiguió exactamente lo que necesitaba para hacer que esta animación funcione tal como la necesito. Estoy intentando duplicar la animación como se ve en Android cuando selecciono un campo de texto con la etiqueta encogiendo más pequeño y hacia arriba y hacia la izquierda. Solo una transformación de escala reduce la etiqueta, pero hacia abajo y hacia la derecha. La transformación de traducción también fue necesaria, pero no pude encontrar la manera de hacer que ambos trabajaran. CGAffineTransformConcat fue la clave. ¡Gracias! – magnusMTB

Cuestiones relacionadas