uiviewcontrolleranimatedtransitioning custom ios ios7 custom-transition

ios - custom - transitions swift



UIPercentDrivenInteractiveTransition produciendo animación extraña cuando se hace (3)

Estoy usando una transición de inserción personalizada interactiva con un UIPercentDrivenInteractiveTransition . El reconocedor de gestos llama con éxito a updateInteractiveTransition del controlador de updateInteractiveTransition . Del mismo modo, la animación se completa con éxito cuando llamo finishInteractiveTransition del controlador de finishInteractiveTransition .

Pero, a veces me sale un poco más de animación que me distrae al final (donde parece que se repite la última parte de la animación). Con animaciones razonablemente simples, rara vez veo este síntoma en el iPhone 5 (aunque rutinariamente lo veo en el simulador cuando trabajo en una computadora portátil lenta). Si hago que la animación sea más costosa computacionalmente (por ejemplo, muchas sombras, múltiples vistas animando diferentes direcciones, etc.), la frecuencia de este problema en el dispositivo aumenta.

¿Alguien más ha visto este problema y ha encontrado una solución que no sea la simplificación de las animaciones (que debo admitir que de todos modos) y / o escribir mis propios controladores de interacción? El enfoque UIPercentDrivenInteractiveTransition tiene cierta elegancia, pero me inquieta el hecho de que se comporte de forma no determinista. ¿Han visto otros este comportamiento? ¿Alguien sabe de otras soluciones?

Para ilustrar el efecto, vea la imagen de abajo. Observe cómo la segunda escena, la vista roja, cuando termina la animación, parece repetir la última parte de su animación por segunda vez.

Esta animación es generada por:

  • llamando repetidamente a updateInteractiveTransition , avanzando la actualización del 0% al 40%;

  • pausa momentánea (para que pueda diferenciar entre la transición interactiva y la animación de finalización resultante de finishInteractiveTransition );

  • luego llamando a finishInteractiveTransition para completar la animación; y

  • el bloque de completion la animación del controlador de animación llama a la transitionContext completeTransition para la transitionContext , con el fin de limpiar todo.

Al hacer algunos diagnósticos, parece que es este último paso el que desencadena ese poco de animación extraña. El bloque de finalización del controlador de animación se llama cuando finaliza la animación, pero tan pronto como llamo completeTransition , a veces repite el último bit de la animación (especialmente cuando se usan animaciones complejas).

No creo que sea relevante, pero este es mi código para configurar el controlador de navegación para realizar transiciones interactivas:

- (void)viewDidLoad { [super viewDidLoad]; self.navigationController.delegate = self; self.interationController = [[UIPercentDrivenInteractiveTransition alloc] init]; } - (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController*)fromVC toViewController:(UIViewController*)toVC { if (operation == UINavigationControllerOperationPush) return [[PushAnimator alloc] init]; return nil; } - (id <UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController*)navigationController interactionControllerForAnimationController:(id <UIViewControllerAnimatedTransitioning>)animationController { return self.interationController; }

Mi PushAnimator es:

@implementation PushAnimator - (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext { return 5.0; } - (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext { UIViewController* toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; UIViewController* fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey]; [[transitionContext containerView] addSubview:toViewController.view]; toViewController.view.frame = CGRectOffset(fromViewController.view.frame, fromViewController.view.frame.size.width, 0);; [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{ toViewController.view.frame = fromViewController.view.frame; } completion:^(BOOL finished) { [transitionContext completeTransition:![transitionContext transitionWasCancelled]]; }]; } @end

Tenga en cuenta que cuando coloco la declaración de registro en la que llamo completeTransition , puedo ver que esta animación extraña ocurre después de que llamo completeTransition (aunque la animación se realizó en ese momento). Esto sugeriría que esa animación adicional puede haber sido el resultado de la llamada para completeTransition .

Para tu información, he hecho este experimento con un reconocedor de gestos:

- (void)handlePan:(UIScreenEdgePanGestureRecognizer *)gesture { CGFloat width = gesture.view.frame.size.width; if (gesture.state == UIGestureRecognizerStateBegan) { [self performSegueWithIdentifier:@"pushToSecond" sender:self]; } else if (gesture.state == UIGestureRecognizerStateChanged) { CGPoint translation = [gesture translationInView:gesture.view]; [self.interactionController updateInteractiveTransition:ABS(translation.x / width)]; } else if (gesture.state == UIGestureRecognizerStateEnded || gesture.state == UIGestureRecognizerStateCancelled) { CGPoint translation = [gesture translationInView:gesture.view]; CGPoint velocity = [gesture velocityInView:gesture.view]; CGFloat percent = ABS(translation.x + velocity.x * 0.25 / width); if (percent < 0.5 || gesture.state == UIGestureRecognizerStateCancelled) { [self.interactionController cancelInteractiveTransition]; } else { [self.interactionController finishInteractiveTransition]; } } }

También lo hice llamando a updateInteractiveTransition y finishInteractiveTransition manualmente (eliminando el reconocedor de gestos de la ecuación), y todavía muestra este extraño comportamiento:

[self performSegueWithIdentifier:@"pushToSecond" sender:self]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self.interactionController updateInteractiveTransition:0.40]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self.interactionController finishInteractiveTransition]; }); });

En conclusión, he llegado a la conclusión de que este es un problema aislado para UIPercentDrivenInteractiveTransition con animaciones complejas. Puedo minimizar el problema simplificándolos (p. Ej., Instantáneas y vistas animadas instantáneas). También sospecho que podría resolver esto si no UIPercentDrivenInteractiveTransition y escribo mi propio controlador de interacción, que haría la animación en sí, sin intentar interpolar el bloque animationWithDuration .

Pero me preguntaba si alguien ha descubierto algún otro truco para usar UIPercentDrivenInteractiveTransition con animaciones complejas.


El motivo de este error en mi caso fue establecer que el cuadro de la vista se animara varias veces. Solo estoy configurando el marco de vista UNA VEZ y solucioné mis problemas.

Entonces, en este caso, el cuadro de "toViewController.view" se estableció en DOS VECES, lo que hace que la animación tenga un comportamiento no deseado.



He visto algo similar. Tengo dos soluciones posibles. Una es usar el rendimiento diferido en el controlador de finalización de animación:

} completion:^(BOOL finished) { double delayInSeconds = 0.1; dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)); dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ BOOL cancelled = [transitionContext transitionWasCancelled]; [transitionContext completeTransition:!cancelled]; }); self.interacting = NO; }];

La otra posibilidad es: ¡no uses la animación de porcentajes! Nunca he tenido un problema como este al manejar manualmente la animación interactiva personalizada.