UIPercentDrivenInteractiveTransition führt nach Abschluss zu einer überflüssigen Animation

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

  •  21-12-2019
  •  | 
  •  

Frage

Ich verwende einen interaktiven benutzerdefinierten Push-Übergang mit einem UIPercentDrivenInteractiveTransition.Der Gestenerkenner ruft erfolgreich die Interaktionscontroller auf updateInteractiveTransition.Ebenso wird die Animation erfolgreich abgeschlossen, wenn ich die Interaktionscontroller aufrufe finishInteractiveTransition.

Aber manchmal bekomme ich am Ende eine zusätzliche ablenkende Animation (wo es scheint, als würde sich der letzte Teil der Animation wiederholen).Bei relativ einfachen Animationen sehe ich dieses Symptom selten auf dem iPhone 5 (obwohl ich es regelmäßig im Simulator sehe, wenn ich an einem langsamen Laptop arbeite).Wenn ich die Animation rechenintensiver mache (z. B.viele Schatten, mehrere Ansichten, die unterschiedliche Richtungen animieren usw.), nimmt die Häufigkeit dieses Problems auf dem Gerät zu.

Hat noch jemand dieses Problem gesehen und eine andere Lösung gefunden, als die Animationen zu rationalisieren (was ich zugegebenermaßen sowieso tun sollte) und/oder meine eigenen Interaktionscontroller zu schreiben?Der UIPercentDrivenInteractiveTransition Der Ansatz hat eine gewisse Eleganz, aber ich bin beunruhigt darüber, dass er sich nicht deterministisch schlecht verhält.Haben andere dieses Verhalten gesehen?Kennt jemand andere Lösungen?

Um den Effekt zu veranschaulichen, sehen Sie sich das Bild unten an.Beachten Sie, dass die zweite Szene, die rote Ansicht, am Ende der Animation den letzten Teil der Animation ein zweites Mal zu wiederholen scheint.

animation not right

Diese Animation wird generiert von:

  • immer wieder anrufen updateInteractiveTransition, fortschreitende Aktualisierung von 0 % auf 40 %;

  • kurzzeitiges Anhalten (damit Sie zwischen dem interaktiven Übergang und der daraus resultierenden Abschlussanimation unterscheiden können finishInteractiveTransition);

  • dann anrufen finishInteractiveTransition um die Animation abzuschließen;Und

  • die Animationen des Animationscontrollers completion Anrufe blockieren completeTransition für die transitionContext, um alles aufzuräumen.

Bei einigen Diagnosen scheint es, dass es dieser letzte Schritt ist, der diese überflüssige Animation auslöst.Der Abschlussblock des Animationscontrollers wird aufgerufen, wenn die Animation beendet ist, aber sobald ich aufrufe completeTransition, wiederholt es manchmal den letzten Teil der Animation (insbesondere bei der Verwendung komplexer Animationen).


Ich glaube nicht, dass es relevant ist, aber das ist mein Code zum Konfigurieren des Navigationscontrollers für die Durchführung interaktiver Übergänge:

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

Mein PushAnimator Ist:

@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

Beachten Sie, wenn ich die Protokollierungsanweisung dort einfüge, wo ich anrufe completeTransition, kann ich sehen, dass diese überflüssige Animation passiert, nachdem ich anrufe completeTransition (obwohl die Animation zu diesem Zeitpunkt tatsächlich fertig war).Dies würde darauf hindeuten, dass diese zusätzliche Animation möglicherweise auf den Aufruf von zurückzuführen ist completeTransition.

Zu Ihrer Information, ich habe dieses Experiment mit einem Gestenerkenner durchgeführt:

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

Ich habe es auch getan, indem ich angerufen habe updateInteractiveTransition Und finishInteractiveTransition manuell (wobei die Gestenerkennung aus der Gleichung entfernt wird), und es zeigt immer noch dieses seltsame Verhalten:

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

Unterm Strich bin ich zu dem Schluss gekommen, dass dies ein isoliertes Problem ist UIPercentDrivenInteractiveTransition mit komplexen Animationen.Ich kann das Problem minimieren, indem ich sie vereinfache (z. B.Schnappschüsse und animierte Schnappschussansichten).Ich vermute auch, dass ich das Problem lösen könnte, indem ich es nicht verwende UIPercentDrivenInteractiveTransition und ich schreibe meinen eigenen Interaktionscontroller, der die Animation selbst ausführt, ohne zu versuchen, sie zu interpolieren animationWithDuration Block.

Aber ich habe mich gefragt, ob jemand andere Tricks zur Verwendung herausgefunden hat UIPercentDrivenInteractiveTransition mit komplexen Animationen.

War es hilfreich?

Lösung

Ich habe etwas Ähnliches gesehen.Ich habe zwei mögliche Problemumgehungen.Eine besteht darin, die verzögerte Leistung im Animationsabschluss-Handler zu verwenden:

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

Die andere Möglichkeit ist:Verwenden Sie keine prozentuale Antriebsanimation!Ich habe niemals hatte ein Problem wie dieses beim Ansteuern der interaktiven benutzerdefinierten Animation ich selbst manuell.

Andere Tipps

Dieses Problem tritt nur im Simulator auf.

LÖSUNG:self.interactiveAnimator.completionSpeed ​​= 0,999;

Fehler hier gemeldet: http://openradar.appspot.com/14675246

Der Grund für diesen Fehler war in meinem Fall das mehrfache Festlegen des Rahmens der zu animierenden Ansicht.Ich stelle den Ansichtsrahmen nur EINMAL ein und es hat meine Probleme behoben.

In diesem Fall wurde der Frame von „toViewController.view“ also ZWEIMAL gesetzt, wodurch die Animation ein unerwünschtes Verhalten aufwies

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top