objective framework developer apple iphone animation core-animation properties

iphone - framework - CABasicAnimation no anima mi propiedad



swift ios documentation (3)

La ruta de la clave solo debería ser la ruta clave de la propiedad, no el nombre del objeto también.

Utilizar esta

[CABasicAnimation animationWithKeyPath:@"frame"]

en lugar de esto

[CABasicAnimation animationWithKeyPath:@"layerImage.frame"]

Y solo por cierto, cuando agrega animación a una capa, la clave no significa la propiedad clave para animar. Solo la tecla (nombre) que desea que tenga esta animación (esto se refiere a la última línea de su código)

He estado tratando de entender qué está mal con mi animación y aún no lo he resuelto. Creo que debería ser muy sencillo, pero probablemente haya algo que me falta, incluso después de leer muchos ejemplos y documentación.

Mi problema proviene originalmente del hecho de que en el iPhone, no puede cambiar el tamaño de las capas automáticamente (con la vista). La documentación dice lo contrario, pero no hay autoresizeMask para la capa en los SDK. Así que decidí hacer una pequeña solución y animar la capa yo mismo.

Tengo esta simple pieza de código que debería hacer una animación de cambio de tamaño simple. Los valores son buenos e incluso configuro el delegado para rastrear si el inicio / fin del anim.

// I''ve got a property named layerImage (which is a CALayer) - (void)animateTestWithFrame:(CGRect)value { CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"layerImage.frame"]; animation.duration = 1; animation.fromValue = [NSValue valueWithCGRect:self.frame]; animation.toValue = [NSValue valueWithCGRect:value]; animation.removedOnCompletion = YES; animation.delegate = self; [self.layer addAnimation:animation forKey:@"layerImage.frame"]; }

Entonces, ¿alguna idea? (Esta vista que contiene el código es la subvista de una subvista de la ventana si eso pudiera marcar la diferencia)

--- EDITAR ---

Parece que frame no es animable a través de CABasicAnimation y la propiedad llamada "frame". Cuando uso límites, tengo un resultado extraño, pero al menos obtengo algo. Seguiremos investigando sobre esto.


Así que es bueno que haya descubierto las cosas aquí, pero su respuesta a su propia pregunta tiene algunas inexactitudes. Permíteme corregir algunas cosas:

La propiedad del marco puede ser animada, pero no con animación explícita. Si haces lo siguiente en una capa que no sea la capa raíz de una vista, el cuadro se animará perfectamente:

[CATransaction begin]; [CATransaction setAnimationDuration:2.0f]; [animationLayer setFrame:CGRectMake(100.0f, 100.0f, 100.0f, 100.0f)]; [CATransaction commit];

Recuerde que establecer una propiedad en una capa animará ese cambio de propiedad de forma predeterminada . De hecho, debe desactivar las animaciones en un cambio de propiedad si no desea que se anime. (Por supuesto, esto solo es cierto si está animando una capa que no sea la capa raíz de una vista). Tiene razón al animar tanto la posición como los límites si necesita usar una animación explícita.

Puedes animar el cuadro en una UIView usando animación implícita:

[UIView beginAnimations:nil context:NULL]; [UIView setAnimationDuration:3.0f]; [[self view] setFrame:CGRectMake(45.0f, 45.0f, 100.0f, 100.0f)]; [UIView commitAnimations];

Esto animará desde el marco actual de la vista (límites y posición) a x = 45.0, y = 45.0, w = 100.0, h = 100.0.

Parece que también puede estar malinterpretando la diferencia entre una animación y una capa. Agrega animaciones a las capas, pero agregar una animación a una capa no establece automáticamente la propiedad que está animando.

CALayers son objetos modelo. Contienen información sobre la capa que eventualmente se procesa en la pantalla. Debe establecer la propiedad de una capa si desea que esa propiedad tenga realmente ese valor. Si simplemente anima la propiedad, solo será una representación visual y no real, lo que significa que el valor vuelve al valor original de la capa porque nunca la cambió realmente.

Lo que me lleva al siguiente punto. Tu dijiste:

Use "animation.removedOnCompletion = NO; animation.fillMode = kCAFillModeForwards;" para asegurarse de que los valores no se restablecen al final de la animación

Esto no es exactamente correcto. Estos dos valores simplemente hacen que la animación permanezca en su posición final visualmente , sin embargo, los valores reales de la capa no han cambiado. Siguen siendo exactamente los mismos valores que cuando comenzaste la animación. En general (con algunas excepciones) no desea utilizar estos dos parámetros porque son solo visuales . Lo que desea es establecer realmente el valor de capa para la propiedad que está animando.

Digamos, por ejemplo, que desea animar la posición de su capa utilizando una animación explícita. Aquí está el código que desea:

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"]; [animation setFromValue:[NSValue valueWithCGPoint:CGPointMake(70.0f, 70.0f)]]; [animation setToValue:[NSValue valueWithCGPoint:CGPointMake(150.0f, 150.0f)]]; [animation setDuration:2.0f]; // Actually set the position on the *layer* that you want it to be // when the animation finishes. [animationLayer setPosition:CGPointMake(150.0f, 150.0f)]; // Add the animation for the position key to ensure that you // override the animation for position changes with your animation. [animationLayer addAnimation:animation forKey:@"position"];

También es posible que desee considerar la agrupación de animación. Con un grupo de animación, puede agrupar varias animaciones y luego controlar cómo se relacionan entre sí. En su caso, la duración de sus límites y las animaciones de posición son las mismas, por lo que lo que está intentando hacer funcionará bien sin un grupo, pero si desea compensar el inicio de las animaciones, por ejemplo, no desea el puesto. animación para comenzar hasta uno o dos segundos en la animación de cuadros, puede escalonarlos configurando el valor de inicio de la animación de posición.

Finalmente, me gustaría saber por qué no puedes usar las animaciones implícitas disponibles en UIView. Los uso en la gran mayoría del código Core Animation que escribo y no puedo ver por qué esto no funcionaría para su situación.

Atentamente.


Entonces, la solución fue animar los @ "límites" y la @ "posición" de la capa porque el marco no es animable en iPhone. Me llevó algo de tiempo entender que la posición era el centro de la capa y que el tamaño de los límites se extendía desde el centro, pero esa era la parte fácil.

Entonces, lo que hice en resumir fue:

  1. En setFrame, crea 2 animaciones con los límites y la propiedad de posición.
  2. Use "animation.removedOnCompletion = NO; animation.fillMode = kCAFillModeForwards;" para asegurarse de que los valores no se restablecen al final de la animación
  3. Registre al delegado en self para implementar "animationDidStop: finished:". Parece que todavía necesita establecer los valores: "layerImage.bounds = [animation.toValue CGRectValue]; layerImage.position = [animation.toValue CGPointValue];".

No pude usar el sistema de animación UIView directamente porque no estaba haciendo lo que quería en las capas.

Gracias tadej5553 por señalarme el problema de capa que tuve con el "addAnimation". Así que aquí está el código para aquellos que quieran ver cómo se ve.

- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag { CABasicAnimation *animation = (CABasicAnimation*)anim; if ([animation.keyPath isEqualToString:@"bounds"]) { layerImage.bounds = [animation.toValue CGRectValue]; } else if ([animation.keyPath isEqualToString:@"position"]) { layerImage.position = [animation.toValue CGPointValue]; } } - (void)setFrame:(CGRect)value { CGRect bounds = CGRectMake(0, 0, value.size.width, value.size.height); if ([UIView isAnimationStarted]) { // animate the bounds CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"bounds"]; animation.duration = [UIView animationDuration]; animation.fromValue = [NSValue valueWithCGRect:layerImage.bounds]; animation.toValue = [NSValue valueWithCGRect:bounds]; animation.removedOnCompletion = NO; animation.fillMode = kCAFillModeForwards; animation.timingFunction = [UIView animationFunction]; animation.delegate = self; [layerImage addAnimation:animation forKey:@"BoundsAnimation"]; // animate the position so it stays at 0, 0 of the frame. animation = [CABasicAnimation animationWithKeyPath:@"position"]; animation.duration = [UIView animationDuration]; animation.fromValue = [NSValue valueWithCGPoint:layerImage.position]; animation.toValue = [NSValue valueWithCGPoint:CGPointMake(bounds.size.width / 2, bounds.size.height / 2)]; animation.removedOnCompletion = NO; animation.fillMode = kCAFillModeForwards; animation.timingFunction = [UIView animationFunction]; animation.delegate = self; [layerImage addAnimation:animation forKey:@"PositionAnimation"]; } else { layerImage.frame = bounds; } [super setFrame:value]; }