UIPercentDrivenInteractiveTransition produisant une animation superflue une fois terminé

StackOverflow https://stackoverflow.com//questions/23047350

  •  21-12-2019
  •  | 
  •  

Question

J'utilise une transition push personnalisée interactive avec un UIPercentDrivenInteractiveTransition.Le système de reconnaissance de gestes appelle avec succès le contrôleur d'interaction updateInteractiveTransition.De même, l'animation se termine avec succès lorsque j'appelle le contrôleur d'interaction finishInteractiveTransition.

Mais parfois, j'obtiens un peu d'animation distrayante à la fin (où elle semble répéter la dernière partie de l'animation).Avec des animations raisonnablement simples, je vois rarement ce symptôme sur l'iPhone 5 (même si je le vois régulièrement sur le simulateur lorsque je travaille sur un ordinateur portable lent).Si je rends l'animation plus coûteuse en termes de calcul (par ex.beaucoup d'ombres, plusieurs vues animant différentes directions, etc.), la fréquence de ce problème sur l'appareil augmente.

Quelqu'un d'autre a-t-il vu ce problème et trouvé une solution autre que la rationalisation des animations (ce que je devrais certes faire de toute façon) et/ou l'écriture de mes propres contrôleurs d'interaction ?Le UIPercentDrivenInteractiveTransition L'approche a une certaine élégance, mais je suis mal à l'aise avec le fait qu'elle se comporte mal de manière non déterministe.D'autres ont-ils vu ce comportement ?Quelqu'un connaît-il d'autres solutions ?

Pour illustrer l’effet, voir l’image ci-dessous.Remarquez comment la deuxième scène, la vue rouge, lorsque l'animation se termine, semble répéter la dernière partie de son animation une seconde fois.

animation not right

Cette animation est générée par :

  • appeler à plusieurs reprises updateInteractiveTransition, mise à jour progressive de 0% à 40% ;

  • en faisant une pause momentanée (afin que vous puissiez faire la différence entre la transition interactive et l'animation d'achèvement résultant de finishInteractiveTransition);

  • puis j'appelle finishInteractiveTransition pour terminer l'animation ;et

  • l'animation du contrôleur d'animation completion bloquer les appels completeTransition pour le transitionContext, afin de tout nettoyer.

En effectuant quelques diagnostics, il semble que c'est cette dernière étape qui déclenche ce morceau d'animation superflu.Le bloc de complétion du contrôleur d'animation est appelé lorsque l'animation est terminée, mais dès que j'appelle completeTransition, il répète parfois le dernier morceau de l'animation (notamment lors de l'utilisation d'animations complexes).


Je ne pense pas que ce soit pertinent, mais voici mon code pour configurer le contrôleur de navigation pour effectuer des transitions interactives :

- (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;
}

Mon PushAnimator est:

@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

Notez que lorsque je mets l'instruction de journalisation là où j'appelle completeTransition, je peux voir que cette animation superflue se produit après avoir appelé completeTransition (même si l'animation était vraiment réalisée à ce moment-là).Cela suggère que cette animation supplémentaire pourrait être le résultat de l'appel à completeTransition.

Pour info, j'ai fait cette expérience avec un outil de reconnaissance de gestes :

- (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];
        }
    }
}

Je l'ai aussi fait en appelant le updateInteractiveTransition et finishInteractiveTransition manuellement (en éliminant le système de reconnaissance de gestes de l'équation), et il présente toujours ce comportement étrange :

[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 fin de compte, j'ai conclu qu'il s'agissait d'un problème isolé UIPercentDrivenInteractiveTransition avec des animations complexes.Je peux minimiser le problème en les simplifiant (par ex.instantanés et vues instantanées animées).Je pense aussi que je pourrais résoudre ce problème en n'utilisant pas UIPercentDrivenInteractiveTransition et écrire mon propre contrôleur d'interaction, qui ferait l'animation elle-même, sans essayer d'interpoler le animationWithDuration bloc.

Mais je me demandais si quelqu'un avait trouvé d'autres astuces pour utiliser UIPercentDrivenInteractiveTransition avec des animations complexes.

Était-ce utile?

La solution

J'ai vu quelque chose de similaire.J'ai deux solutions de contournement possibles.La première consiste à utiliser des performances retardées dans le gestionnaire de complétion d’animation :

} 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;
}];

L'autre possibilité est :n'utilisez pas d'animation à pourcentage !j'ai jamais j'ai eu un problème comme celui-ci lors du pilotage de l'animation personnalisée interactive moi-même manuellement.

Autres conseils

Ce problème ne se pose qu'en simulateur.

SOLUTION:self.interactiveAnimator.completionSpeed ​​= 0,999 ;

bug signalé ici : http://openradar.appspot.com/14675246

La raison de cette erreur dans mon cas était la définition du cadre de la vue animée plusieurs fois.Je ne règle le cadre de vue qu'UNE FOIS et cela a résolu mes problèmes.

Donc, dans ce cas, le cadre de "toViewController.view" a été défini DEUX FOIS, donnant ainsi à l'animation un comportement indésirable

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top