2011-01-20 8 views
22

Todos y cada uno de los libros afirman que hay animaciones implícitas en CALayer. Sin embargo, cada vez que quería verificar eso hasta el momento, termino con un ajuste rápido al valor establecido. Sin animación en absoluto.¿Cuándo exactamente ocurren las animaciones implícitas en iOS?

Aquí hay un ejemplo en un proyecto donde nada más está sucediendo. Todo lo que hago es crear una vista, luego obtener su instancia CALayer y hacer algo que debe ser animado implícitamente.

[theLayer setValue:[NSNumber numberWithFloat:M_PI * 1.1] forKeyPath:@"transform.rotation.z"]; 

Otra:

CGRect currentBounds = theLayer.bounds; 
currentBounds.size.width += 120.f; 
[self.animatedLayer setBounds:currentBounds]; 

la vista contiene algunas cosas, por supuesto, para que pueda ver el cambio. Veo el cambio visual, pero como un chasquido. Sin animación en absoluto.

Entonces, o todos esos libros son incorrectos y tienen en mente el conocimiento anterior de Mac OS X cuando escribo sobre Core Animation y animaciones implícitas, o estoy haciendo algo mal. ¿Alguien puede proporcionar un ejemplo de trabajo que demuestre animaciones implícitas en el iPhone?

Respuesta

65

UIKit deshabilita las animaciones implícitas. Para ser más específico, un CALayer asociado con un UIView nunca animará implícitamente. Los usuarios de CAL que creas tú mismo y que no están asociados a un UIView comprarán en la maquinaria de animación implícita normal.

Si le interesa cómo funciona esto, las animaciones implícitas suceden después de la normal -actionForKey: búsqueda. Si hay una CAAction para una propiedad determinada, se usa. De lo contrario, se utiliza la animación implícita. En el caso de un CALayer asociado con un UIView, UIView implementa el método delegado -actionForLayer:forKey:, y cuando no está en un bloque de animación UIView siempre devuelve [NSNull null] para indicar que la búsqueda de acción debe detenerse aquí. Esto evita que las animaciones implícitas funcionen. Dentro de un bloque de animación UIView, construye su propia acción para representar la configuración de animación actual de UIView. De nuevo, esto evita las animaciones implícitas.

Si necesita animar las propiedades de CALayer que UIView no hará por usted, puede usar una subclase de CAAnimation explícita (como CABasicAnimation).

+1

¡Excelente respuesta! Tengo curiosidad, ¿de dónde sacaste toda esta información detallada? Revisé tantos libros y fuentes, pero carecen de estos detalles. –

+0

Mayormente de prueba y error. Si reemplaza '-actionForLayer: forKey:' en una subclase de UIView, puede desconectar los resultados de la llamada a super y correlacionar eso con si hay un bloque de animación activo. También tiene sentido si lo piensas: UIView es el delegado de CALayer, y '-actionForLayer: forKey:' es el lugar apropiado para engancharte si deseas inhabilitar las animaciones implícitas. –

+0

Tiene mucho sentido. ¡Gracias! –

0

También podría establecer el delegado de la capa en su propio objeto y manejar -actionForLayer: forKey :. Parece que se obtiene una animación implícita incluso si el delegado no implementa -actionForLayer: forKey :.

2

Publicación anterior, pero el enlace a continuación apunta a una sección en la Guía de programación de animación básica que ayuda a arrojar algo más de luz sobre lo que Kevin Ballard estaba diciendo. Realmente debe haber una nota descarada que mencione que para animar las propiedades de capa subyacentes de UIView debe asegurarse de configurar el delegado de la capa en una instancia que adoptará el método "actionForLayer: ForKey:" y devolverá nil. Se ha descubierto que también puede configurar el delegado en una instancia que no adopta este método y que aún permite animaciones implícitas, pero esta es una práctica descuidada y confusa.

Core Animation - Layer Actions - Defined Search Pattern for Action Keys

1

Tenga en cuenta que subcapas de la capa primaria de un UIView normalmente no tienen la UIView como su delegado. Por lo tanto, participan en animación implícita a menos que lo bloquee explícitamente, incluso si no ha proporcionado un delegado para devolver una acción nula en respuesta a actionForLayer: forKey :.

Entonces, una forma simple de obtener animación implícita en una vista genérica es simplemente agregar una subcapa que cubra la capa primaria.

El libro de programación de Matt Neuberg iOS 5 (actualmente en versión beta en Safari Books Online) explica este tema con mucha lucidez.

1

Es exactamente correcto de la respuesta de Kevin Ballard. Quiero brindar algo más aquí.

La información de detalle de la official document

hay una sección llamada: Reglas para la modificación de las capas en IOS, y encontrará

La clase UIView desactiva las animaciones de capa por defecto, pero les vuelve a habilitar el interior de animación bloques.

Excepto habilitar lo implícito en el bloque de animación UIView. Hay dos soluciones más:

  1. Haga que la capa que necesita animación sea una subcapa de una vista. Consulte la [respuesta] [2]

    [2]: Implicit property animations do not work with CAReplicatorLayer? del fade-in de animación implícita no funciona. Intenté esto, funcionó como se esperaba.

  2. asigna el delegado de la capa a la propia capa. El delegado predeterminado de la capa en iOS es su vista de almacén de respaldo que implementa la clave actionForLayer: (id) layer forKey: (NSString *) y devuelve [NSNull null] para deshabilitar la animación implícita de la capa.
0

En realidad, podría simplemente devolver nil para obtener la animación predeterminada de CALay. nil (NSString *) evento { retorno;:

  • (id) actionForLayer: (CALayer *) capa forKey }
+0

/* Si está definido, llamado por la implementación predeterminada del método * -actionForKey :. Debería devolver un objeto que implemente el protocolo CAAction *. Puede devolver 'nil' si el delegado no especifica * un comportamiento para el evento actual.Devolver el objeto nulo (es decir, * '[NSNull null]') no obliga a realizar más búsquedas. (Es decir, no se llamará al método * + defaultActionForKey). * / – dongxin

Cuestiones relacionadas