UIPercentDrivenInteractiveTransition produciendo extraños animación cuando se hace
-
21-12-2019 - |
Pregunta
Estoy usando un interactivos personalizados de inserción en la transición con una UIPercentDrivenInteractiveTransition
.El gesto de reconocimiento con éxito llama a la interacción del controlador updateInteractiveTransition
.Asimismo, la animación completa con éxito cuando yo llame a la interacción del controlador finishInteractiveTransition
.
Pero, a veces me pongo un poco más de la distracción de la animación al final (donde parece repetir la última parte de la animación).Con razonablemente animaciones simples, rara vez veo este síntoma en el iPhone 5 (aunque me vea en el simulador cuando se trabaja en lento portátil).Si puedo hacer la animación más computacionalmente costosos (por ejemplo,un montón de sombras, múltiples puntos de vista de la animación de diferentes direcciones, etc.), la frecuencia de este problema en el dispositivo aumenta.
Ha alguien más visto este problema y encontré una solución que no sea la racionalización de las animaciones (que admito que debe hacer de todos modos) y/o a escribir mi propia interacción de los controladores?El UIPercentDrivenInteractiveTransition
el enfoque tiene una cierta elegancia, pero estoy incómodo con el hecho de que se porta mal no determinista.Otros visto este comportamiento?¿Alguien sabe de otras soluciones?
Para ilustrar el efecto, ver la imagen de abajo.Observe cómo la segunda escena, el rojo de la vista, cuando la animación termina, parece repetir la última parte de su animación por segunda vez.
Esta animación es generada por:
varias veces
updateInteractiveTransition
, progresa actualización de 0% a 40%;momentáneamente la pausa (así se puede diferenciar entre la interactiva y la transición de la finalización de la animación resultante de
finishInteractiveTransition
);a continuación, llamar a
finishInteractiveTransition
para completar la animación;yla animación del controlador de la animación
completion
bloquear llamadascompleteTransition
para eltransitionContext
, con el fin de limpiar todo.
Hacer algunos diagnósticos, parece que es el último paso que provoca la extraña poco de animación.La animación del controlador de la finalización del bloque es llamado cuando la animación está terminado, pero tan pronto como yo lo llamo completeTransition
, a veces se repite el último bit de la animación (especialmente cuando se utiliza animaciones complejas).
Yo no creo que sea relevante, pero este es mi código para configurar el controlador de navegación para realizar interactivo de transiciones:
- (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
Nota, cuando pongo el registro de instrucción donde puedo llamar completeTransition
, Puedo ver que esta extraña poco de animación que sucede después de que me llame completeTransition
(aunque la animación se hizo realidad en ese punto).Esto sugeriría que el extra de animación pueden haber sido resultado de la llamada a completeTransition
.
Para su INFORMACIÓN, he hecho este experimento con un gesto de reconocimiento:
- (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];
}
}
}
Yo también lo hizo por llamar la updateInteractiveTransition
y finishInteractiveTransition
manualmente (eliminando el gesto de reconocimiento a partir de la ecuación), y todavía exhibe este comportamiento extraño:
[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];
});
});
Línea de fondo, he llegado a la conclusión de que este es un problema aislado para UIPercentDrivenInteractiveTransition
con animaciones complejas.Me puede minimizar el problema, mediante la simplificación de los mismos (p. ej.creación de instantáneas y animado snapshotted vistas).También sospecho yo podría resolver este por no usar UIPercentDrivenInteractiveTransition
y escribir mi propia interacción del controlador, que iba a hacer la animación en sí, sin tratar de interpolar la animationWithDuration
el bloque.
Pero me preguntaba si alguien ha averiguado cualquier otros trucos para el uso de UIPercentDrivenInteractiveTransition
con animaciones complejas.
Solución
He visto algo similar.Tengo dos posibles soluciones.Uno es el uso de retraso en la animación controlador de finalizació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 utilizar por ciento-de la unidad de animación!He nunca había un problema como este, cuando la conducción de la interactivos personalizados de animación yo de forma manual.
Otros consejos
Este problema sólo se plantea en el simulador.
SOLUCIÓN:auto.interactiveAnimator.completionSpeed = 0.999;
error reportado aquí: http://openradar.appspot.com/14675246
La razón de este error en mi caso fue el de establecer el marco de la vista de la animación varias veces.Sólo estoy configurando el cuadro de vista de una VEZ solucionado mis problemas.
En este caso, en el marco de "toViewController.ver" fue establecido dos veces, con lo que la animación tiene un comportamiento no deseado