2010-07-01 31 views
6

Me gustaría animar entre dos estados de una vista. Digamos, por ejemplo, que tengo una vista con una etiqueta y cuando cambio el texto de la etiqueta, una animación hace que eso cambie cuando la página se voltea.Animación entre dos estados de una vista, usando animación personalizada

Ahora usted puede hacer, por supuesto, esto con un [UIView setAnimationTransition:forView:cache:]:

- (IBAction)nextPage { 
    [UIView beginAnimation:nil context:nil]; 
    [UIView setAnimationDuration:1]; 
    [UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:pageView cache:NO]; 
    label.text = @"page 2"; 
    [UIView commitAnimations]; 
} 

- (IBAction)previousPage { 
    [UIView beginAnimation:nil context:nil]; 
    [UIView setAnimationDuration:1]; 
    [UIView setAnimationTransition:UIViewAnimationTransitionCurlDown forView:pageView cache:NO]; 
    label.text = @"page 1"; 
    [UIView commitAnimations]; 
} 

... pero entonces no puede utilizar su propia animación personalizada, le pegan a las animaciones integradas (que están bien, pero no están hechos a la medida de mis necesidades).

Así que la otra opción es añadir una capa de CAAnimation a la vista:

- (IBAction)nextPage { 
    CAAnimation *animation = [self animationWithDuration:1 forward:NO]; 
    [pageView.layer addAnimation:animation forKey:@"pageTransition"]; 
    label.text = @"page 2"; 
} 

- (IBAction)previousPage { 
    CAAnimation *animation = [self animationWithDuration:1 forward:YES]; 
    [pageView.layer addAnimation:animation forKey:@"pageTransition"]; 
    label.text = @"page 1"; 
} 

continuación son libres para determinar lo Core Animation Animación le permite hacer. Esto funciona bien si defino una animación CATransition, por ejemplo un kCATransitionReveal: una vista en el estado "página 2" aparece debajo de la vista en el estado "página 1" cuando se sale.

- (CAAnimation *)animationWithDuration:(float)duration forward:(BOOL)forward { 
    CATransition *animation = [CATransition animation]; 
    [animation setType:kCATransitionReveal]; 
    [animation setSubtype:forward?kCATransitionFromLeft:kCATransitionFromRight]; 
    [animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]]; 

    animation.duration = duration; 
    return animation; 
} 

Pero cuando defino la animación a ser por ejemplo un CABasicAnimation, sólo un estado de la vista es visible.

- (CAAnimation *)animationWithDuration:(float)duration forward:(BOOL)forward { 
    CATransform3D transform = CATransform3DIdentity; 
    transform.m34 = 1.0/-1000; 
    transform = CATransform3DRotate(transform, M_PI, 0.0f, 1.0f, 0.0f); 
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform"]; 
    if(forward) { 
     animation.fromValue = [NSValue valueWithCATransform3D:transform]; 
    } else { 
     animation.toValue = [NSValue valueWithCATransform3D:transform]; 
    } 

    animation.duration = duration; 
    return animation; 
} 

En su lugar, me gustaría que la vista en el estado "página 1" a permanecer visible hasta el final de la animación mientras que la vista en el estado "página 2" entra en el marco, tal y como se comporta con una animación de transición.

Por supuesto, siempre podría meterme con la duplicación de la vista y hacer que una aparezca como una vista de hermanos mientras la animo y la elimino de la supervista al finalizar ... pero debe haber una forma mucho más directa de lograr este efecto de animación bastante simple sin jugar con las vistas.

Probablemente algo que contar a la capa, pero luego no sé qué, y ahí es donde necesito su ayuda, chicos :)

Gracias!

Respuesta

0

Bueno, puede crear una capa, configurar su contenido en una imagen que represente su estado final de vista, que aplicar la animación a esta capa. Cuando finalice la animación, puede eliminar la capa y cambiar el estado de la vista.

Creo que esto funcionará mejor que la creación de una vista completa.

1

Recientemente realicé una transición de diapositiva personalizada entre las subvistas en un controlador. Mi enfoque fue tomar un mapa de bits de la vista y la vista, agregarlos a una vista y animar esa vista. Al final, puedes eliminar la vista de transición y mostrar la vista en. He aquí un fragmento del método de transición:

-(void) transitionToView:(UIView *)viewIn lastView:(UIView *)viewOut slideRight:(BOOL)isRight { 
UIGraphicsBeginImageContext(viewOut.frame.size); 

UIImageView *bitmapOut = [[UIImageView alloc] initWithFrame: viewOut.frame]; 

[viewOut.layer renderInContext:UIGraphicsGetCurrentContext()]; 
UIImage *viewOutImage = UIGraphicsGetImageFromCurrentImageContext(); 
UIGraphicsEndImageContext(); 
bitmapOut.image = viewOutImage; 

UIImageView *bitmapIn = [[UIImageView alloc] initWithFrame: viewIn.frame ]; 
bitmapIn.frame = CGRectMake(isRight ? 320 : -320, bitmapIn.frame.origin.y, bitmapIn.frame.size.width, bitmapIn.frame.size.height); 
UIGraphicsBeginImageContext(viewIn.frame.size); 

[viewIn.layer renderInContext:UIGraphicsGetCurrentContext()]; 
UIImage *viewInImage = UIGraphicsGetImageFromCurrentImageContext(); 
UIGraphicsEndImageContext(); 

bitmapIn.image = viewInImage; 

[self.view addSubview:transitionContainer]; 

[transitionContainer addSubview:bitmapIn]; 
[transitionContainer addSubview:bitmapOut]; 

[self removeAllViews]; 

[UIView beginAnimations:nil context:nil]; 
[UIView setAnimationDuration:0.5f]; 
[UIView setAnimationDelegate:self]; 
[UIView setAnimationDidStopSelector:@selector(swapViewsAtEndOfTransition:)]; 
transitionContainer.frame = CGRectMake(isRight ? -320 : 320, 0, 640, 411); 
[UIView commitAnimations]; 

[bitmapOut release]; bitmapOut = nil; 
[bitmapIn release]; bitmapIn = nil;} 

A continuación, en el selector de swapViewsAtEndOfTransition se puede actualizar las vistas en consecuencia.

0

Pasaron los años, pero supongo que encontré una solución para usted. Solo use kCATransitionPush en lugar de kCATransitionReveal. De esta manera:

- (CAAnimation *)animationWithDuration:(float)duration forward:(BOOL)forward { 
    CATransition *animation = [CATransition animation]; 
    [animation setType:kCATransitionPush]; 
    [animation setSubtype:forward?kCATransitionFromLeft:kCATransitionFromRight]; 
    [animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]]; 

    animation.duration = duration; 
    return animation; 
} 
Cuestiones relacionadas