iOS 7 custom transition glitch

匿名 (未验证) 提交于 2019-12-03 02:52:02

问题:

This video shows the issue I am having. http://www.youtube.com/watch?v=C9od_2KZAbs

I am attempting to create a custom push interactive transition using a UIPanGestureRecognizer. I have an interactive transition delegate (using UIPercentDrivenInteractiveTransition) and a transition animator.

Here is how the pan gesture controls the transition:

- (void) panGestureRecognized:(UIPanGestureRecognizer *) gestureRecogznier {      CGPoint translation = [gestureRecogznier translationInView:gestureRecogznier.view];      if (gestureRecogznier.state == UIGestureRecognizerStateBegan) {          self.interactiveTransitionAnimator = [[UIPercentDrivenInteractiveTransition alloc] init];          EVDetailViewController *detailViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"EVDetailViewController"];         [self.navigationController pushViewController:detailViewController animated:YES];     }     else if (gestureRecogznier.state == UIGestureRecognizerStateChanged) {          CGFloat d = (translation.x / CGRectGetWidth(self.view.bounds)) * -1;         [self.interactiveTransitionAnimator updateInteractiveTransition:d];     }     else if (gestureRecogznier.state == UIGestureRecognizerStateEnded) {          if ([gestureRecogznier velocityInView:self.view].x < 0) {             [self.interactiveTransitionAnimator finishInteractiveTransition];         } else {             [self.interactiveTransitionAnimator cancelInteractiveTransition];         }          self.interactiveTransitionAnimator = nil;     } } 

The UINavigationControllerDelegate handles the vending of both transition delegate objects, which is triggered when pushViewController: is called.

The transition animator has a very simple animation:

- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext {      UIViewController* toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];     [[transitionContext containerView] addSubview:toViewController.view];      CGRect finalToVCFrame = [transitionContext finalFrameForViewController:toViewController];      if (self.operation == UINavigationControllerOperationPush) {          // set offscreen to the right         toViewController.view.frame = CGRectMake(320.0f, 0.0f, 320.0f, 568.0f);          [UIView animateWithDuration:[self transitionDuration:transitionContext] delay:0.0f options:0 animations:^{              toViewController.view.frame = finalToVCFrame;          } completion:^(BOOL finished) {              // *** When this is called, the glitch occurs             [transitionContext completeTransition:YES];         }];     } } 

In the video, the pan gesture ends about 60% of the way through, which triggers the finishInteractiveTransition call. Everything goes smoothly until the completion block in the UIView block-based animation calls completeTransition:. When this method is called, the toViewController re-animates the last part of the push animation unnecessarily. In the video the red view is the window. The animation duration is 3 seconds.

I cannot figure out why this happens. It looks like the animation between the point when the gesture ends and when completeTransition: is called happens twice. Any ideas?

回答1:

As of iOS 7.1, I can reproduce this in simulator but not on an actual device. Anyway, there appears to be a workaround:

self.interactiveTransitionAnimator.completionSpeed = 0.999; 

There is a radar for this bug: rdar://14675246



回答2:

What happens if you call the [transitionContext completeTransition:YES]; immediately after calling finishInteractiveTransition like this:

else if (gestureRecogznier.state == UIGestureRecognizerStateEnded) {      if ([gestureRecogznier velocityInView:self.view].x < 0) {         [self.interactiveTransitionAnimator finishInteractiveTransition];         [transitionContext completeTransition:YES];     } else {         [self.interactiveTransitionAnimator cancelInteractiveTransition];     }      self.interactiveTransitionAnimator = nil; } 


回答3:

I've got an example on github that works without the glitch. Let me know if you have further questions.



回答4:

Or, as matt observed here, you can also either defer the completeTransition or drive the custom interaction controller yourself:

I've seen something similar. I have two possible workarounds. One is to use delayed performance in the animation completion handler:

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

The other possibility is: don't use percent-drive animation! I've never had a problem like this when driving the interactive custom animation myself manually.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!