5

I am following this tutorial to learn how can I make interactive transitions for UIViewControllers.

Everything works fine but I found some flickering.

The first flicker I found happens when you drag the screen from right to left. This is because the pan gesture will recognize every drag and run the panned(_:) method and will pop or perform a segue to change controllers. I fixed id adding the delegate method gestureRecognizerShouldBegin(_:).

This ensures me that if a drag from right to left is made the gesture is never started (.Begin).

But now I have a different problem. If I drag from left to right (as intended) but, without interrupting the drag, change direction to right to left the transition should be canceled. In this event I can see a brief flicker with the new controller before the old controller is presented again.

What can I do to gracefully cancel the interactive animation?

This is a video trying to show the problem. I could not found a way to slow down this animation so it's very fast.

EDIT

I've tried with 2 different approaches.

This one uses CABasicAnimation to animate the transition. And this one uses animateWithDuration(_:delay:usingSpringWithDamping:initialSpringVelocity:options:animations:completion:)

Both of them still flicker whenever I call cancelInteractiveTransition

Nicos Karalis
  • 3,724
  • 4
  • 33
  • 62
  • Are you using core animation methods? – Sonny Saluja Jun 06 '16 at 18:38
  • @SanjitSaluja Yes, the `UIViewControllerAnimatedTransitioning` object uses Core Animation mask and transforms to de the trick – Nicos Karalis Jun 06 '16 at 18:40
  • I've seen this when I forgot to set the fillMode of the animation to kCAFillModeForwards – Sonny Saluja Jun 06 '16 at 18:41
  • @SanjitSaluja I've just tested, did not work. kCAFillModeForwards or kCAFillModeRemoved I can still see the flicker. Check my edit. – Nicos Karalis Jun 06 '16 at 19:04
  • @NicosKaralis Did you ever solve this issue? – Adam Alyyan Aug 01 '17 at 22:17
  • @AdamAlyyan No I did not, we ended up dropping the project so I didn't find a solution yet – Nicos Karalis Aug 06 '17 at 15:46
  • 1
    The flicker you see is the API attempting to dismiss the view controller non-interactively. This only happens when you cancel the interactive transition. The fix is to make sure that you only begin the interactive transition once (not multiple times as the pan gesture is updating the interaction controller) and to use any available delegate methods to handle touch-ended events and to force the transition to finish or cancel (as you want it). It took me a lot of trial and error to figure this clunky API out but I eventually got it working, better than how some of Apple's own apps handle it. – trndjc Nov 07 '19 at 20:36

1 Answers1

1

This is my way to solve the problem:

- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext {
[UIView animateWithDuration:[self transitionDuration:transitionContext]
                      delay:self.interactive?[self transitionDuration:transitionContext]:0 //  If zero, the animation briefly flashes in iOS 11.
                    options:option
                 animations:^{
                 } completion:^(BOOL finished) {
                 }];
}

the most import thing is delay animation in interactive transition

see code below:I found if we call dismissViewControllerAnimated:YESin UIGestureRecognizerStateBegan, animation immediately start if we don't delay animation。 Then, in UIGestureRecognizerStateChanged , updateInteractiveTransition:progress will bring view to "progress position"。It seems a flash

 switch (sender.state) {
    case UIGestureRecognizerStateBegan:
        _interactive = YES;
        [viewcontroller dismissViewControllerAnimated:YES completion:nil];
        break;
    case UIGestureRecognizerStateChanged:
        [self updateInteractiveTransition:progress];
        break;
    case UIGestureRecognizerStateEnded:
    {
        _interactive = NO;
        if (shouleFinish) {
            [self finishInteractiveTransition];
        } else {
            [self cancelInteractiveTransition];
        }
    }
        break;
    case UIGestureRecognizerStateCancelled:
        _interactive = NO;
        [self cancelInteractiveTransition];
        break;
    default:
        break;
wlixcc
  • 1,132
  • 10
  • 14