iOS 7只在一些时间使用自定义交互式转换

所以我有一个UINavigationController,控制器A作为根控制器。

当我想推控制器B在顶部,我想要使用自定义animation过渡和自定义交互式转换。 这工作正常。

当我想推控制器C顶部,我想回落到UINavigationController 默认的推/popup转换。 为了做到这一点,我返回零

navigationController:animationControllerForOperation:fromViewController:toViewController: 

然而,如果你返回零,那么

 navigationController:interactionControllerForAnimationController: 

将永远不会被调用,默认的“从左边缘平移”popup交互式转换不起作用。

有没有办法返回默认的推/animationanimation控制器和交互控制器? (是否存在id<UIViewControllerAnimatedTransitioning>id<UIViewControllerInteractiveTransitioning>具体实现?)

或者其他方式?

您应该将NavigationController的interactivePopGestureRecognizer委托设置为self,然后在-gestureRecognizerShouldBegin中处理其行为:

也就是说,当你想要触发内置的popup手势时,你必须从这个方法返回YES。 您的自定义手势也一样 – 您必须弄清楚您正在处理的识别器。

 - (void)setup { self.interactiveGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleTransitionGesture:)]; self.interactiveGestureRecognizer.delegate = self; [self.navigationController.view addGestureRecognizer:self.interactiveGestureRecognizer]; self.navigationController.interactivePopGestureRecognizer.delegate = self; } - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer { // Don't handle gestures if navigation controller is still animating a transition if ([self.navigationController.transitionCoordinator isAnimated]) return NO; if (self.navigationController.viewControllers.count < 2) return NO; UIViewController *fromVC = self.navigationController.viewControllers[self.navigationController.viewControllers.count-1]; UIViewController *toVC = self.navigationController.viewControllers[self.navigationController.viewControllers.count-2]; if ([fromVC isKindOfClass:[ViewControllerB class]] && [toVC isKindOfClass:[ViewControllerA class]]) { if (gestureRecognizer == self.interactiveGestureRecognizer) return YES; } else if (gestureRecognizer == self.navigationController.interactivePopGestureRecognizer) { return YES; } return NO; } 

您可以查看您的scheme的示例项目 。 视图控制器A和B之间的转换是自定义animation,用自定义的B> Apopup手势。 视图控制器B和C之间的转换是默认的,带有内置的导航控制器的popup手势。

希望这可以帮助!

例如,您需要每次都设置委托,例如prepareForSeque:。 如果您想要自定义转换,请将其设置为self。 如果你想默认的转换(如默认popup转换)将其设置为零。

在每次转换之前/之后设置委托是一个有效的解决方法,但是如果您实现其他UINavigationControllerDelegate的方法并且需要保留它们,则可以使用Ziconicbuild议的2个委托对象,或者使用NSObject的respondsToSelector: :。 在你的导航委托中,你可以实现:

 - (BOOL)respondsToSelector:(SEL)aSelector { if (aSelector == @selector(navigationController:animationControllerForOperation:fromViewController:toViewController:) || aSelector == @selector(navigationController:interactionControllerForAnimationController:)) { return self.interactivePushTransitionEnabled; } return [super respondsToSelector:aSelector]; } 

然后,您应该确保根据需要更新interactivePushTransitionEnabled 。 在你的例子中,只有当控制器A被显示时,你才应该把属性设置为YES

只有一件事要做:强制UINavigationController重新评估其代表实现的方法。 这可以通过这样做来轻松完成:

 navigationController.delegate = nil; navigationController.delegate = self; // or whatever object you use as the delegate 

尝试设置(self.)navigationController.delegate nil (或返回到以前的值)完成自定义过渡后。

在你的手势识别器中,设置委托(到你自己),并返回你的animation和交互式转换。 当返回交互式转换时,请务必再次取消委托,以便其他所有内容继续使用默认转换。

我在github上有一个工作的例子 。

 - (id<UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController interactionControllerForAnimationController:(id<UIViewControllerAnimatedTransitioning>)animationController { // Unset the delegate so that all other types of transitions (back, normal animated push not initiated by a gesture) get the default behavior. self.navigationController.delegate = nil; if (self.edgePanGestureRecognizer.state == UIGestureRecognizerStateBegan) { self.percentDrivenInteractiveTransition = [UIPercentDrivenInteractiveTransition new]; } else { self.percentDrivenInteractiveTransition = nil; } return self.percentDrivenInteractiveTransition; }