Search code examples
iosobjective-cios7

iOS 7 use custom interactive transitions only some of the time


So I have a UINavigationController, with Controller A as the root controller.

When I want to push Controller B on top, I want to use a custom animated transition and a custom interactive transition. This works fine.

When I want to push Controller C on top, I want to fall back to the default push/pop transitions that comes with UINavigationController. To make this happen I return nil for

navigationController:animationControllerForOperation:fromViewController:toViewController:

however if you return nil, then

navigationController:interactionControllerForAnimationController:

will never be called and the default "pan from left edge" pop interactive transition doesn't work.

Is there a way to return the default push/pop animation controller and interaction controller? (Are there concrete implementations of id<UIViewControllerAnimatedTransitioning> and id<UIViewControllerInteractiveTransitioning>?)

Or some other way?


Solution

  • You should set NavigationController's interactivePopGestureRecognizer delegate to self and then handle its behavior in -gestureRecognizerShouldBegin:

    That is, when you want the built-in pop gesture to fire, you must return YES from this method. The same goes for your custom gestures - you have to figure out which recognizer you are dealing with.

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

    You can check out a sample project for your scenario. Transitions between view controllers A and B are custom animated, with custom B->A pop gesture. Transitions between view controllers B and C are default, with built-in navigation controller's pop gesture.

    Hope this helps!