Domanda

Sto usando una transizione push personalizzata interattiva con un UIPercentDrivenInteractiveTransition. Il riconoscimento dei gesto chiama con successo il updateInteractiveTransition del controller di interazione. Allo stesso modo, l'animazione completa con successo quando chiamo il finishInteractiveTransition del controller di interazione.

Ma, a volte ottengo un po 'in più di animazione distraente alla fine (dove sembra ripetere l'ultima parte dell'animazione). Con animazioni ragionevolmente semplici, raramente vedo questo sintomo su iPhone 5 (anche se lo vedo regolarmente sul simulatore quando si lavora su laptop lento). Se rendo l'animazione più computazionalmente costosa (ad esempio un sacco di ombre, più viste che animano diverse direzioni, ecc.), La frequenza di questo problema sul dispositivo aumenta.

ha chiunque altro ha visto questo problema e ha capito una soluzione diversa dallo snellire le animazioni (che ho certamente dovuto fare comunque) e / o scrivere i miei controller di interazione? L'approccio UIPercentDrivenInteractiveTransition ha una certa eleganza ad esso, ma sono a disagio con il fatto che si comporta male non deterministicamente. Altri hanno visto questo comportamento? Qualcuno sa di altre soluzioni?

Per illustrare l'effetto, vedere l'immagine qui sotto. Nota come la seconda scena, la vista rossa, quando l'animazione finisce, sembra ripetere l'ultima parte della sua animazione una seconda volta.

Animazione non giusta

Questa animazione è generata da:

    .
  • chiamando ripetutamente updateInteractiveTransition, avanzando aggiornamento dallo 0% al 40%;

  • Pausa momentaneamente (in modo da poter differenziare tra la transizione interattiva e l'animazione di completamento risultante da finishInteractiveTransition);

  • quindi chiamare finishInteractiveTransition per completare l'animazione; e

  • Il blocco generacodiccode di animazione del controller dell'animazione chiama completion per il completeTransition, al fine di pulire tutto su.

Facendo qualche diagnostica, sembra che sia questo ultimo passo che attiva quel bit estraneo di animazione. Il blocco di completamento del controller dell'animazione viene chiamato quando l'animazione è finita, ma non appena ho chiamato transitionContext, a volte ripete l'ultimo bit dell'animazione (in particolare quando si utilizza animazioni complesse).


.

Non penso che sia rilevante, ma questo è il mio codice per configurare il controller di navigazione per eseguire transizioni interattive:

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

Il mio completeTransition è:

@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, quando inserisco la dichiarazione di registrazione in cui chiamo PushAnimator, posso vedere che questo bit estraneo di animazione avviene dopo aver chiamato completeTransition (anche se l'animazione è stata davvero fatta in quel punto). Ciò suggerirebbe che l'animazione extra potrebbe essere stata il risultato della chiamata a completeTransition.

FYI, ho fatto questo esperimento con un riconoscimento dei gesti:

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

L'ho fatto anche chiamando manualmente il completeTransition e updateInteractiveTransition (eliminando il riconoscimento dei gesti dall'equazione), e mostra ancora questo strano comportamento:

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

Bottom line, ho concluso che questo è un problema isolato a finishInteractiveTransition con animazioni complesse. Posso ridurre al minimo il problema semplificandoli (ad es. G. SnapShotting e Views snapshotted animate). Sospetto anche che potrei risolvere questo non usando UIPercentDrivenInteractiveTransition e scrivendo il mio controller di interazione, che farebbe l'animazione stessa, senza cercare di interpolare il blocco UIPercentDrivenInteractiveTransition.

Ma mi stavo chiedendo se qualcuno ha capito a nessun altro trucco per usare animationWithDuration con animazioni complesse.

È stato utile?

Soluzione

Ho visto qualcosa di simile.Ho due possibili soluzioni alternative.Uso per utilizzare prestazioni ritardate nel gestore di completamento dell'animazione:

} 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'altra possibilità è: non usare l'animazione per percentuale-drive!Ho mai ha avuto un problema in questo modo quando si guida l'animazione personalizzata interattiva me stesso manualmente.

Altri suggerimenti

Questo problema sorge solo in simulatore.

Soluzione: self.interactiveanimator.ClionsPeed= 0.999;

Bug riportato qui: http://openradar.appspot.com/14675246

Il motivo per questo errore nel mio caso stava impostando il fotogramma della vista che viene animato più volte.Sto solo impostando la cornice di vista una volta e ha risolto i miei problemi.

Quindi in questo caso, il fotogramma di "Punto di vistaController.View" è stato impostato due volte, rendendo così l'animazione un comportamento indesiderato

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top