【问题标题】:iOS 7 use custom interactive transitions only some of the timeiOS 7 仅在某些时候使用自定义交互过渡
【发布时间】:2013-11-21 06:07:33
【问题描述】:

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

当我想将控制器 B 推到顶部时,我想使用自定义动画过渡和自定义交互过渡。这很好用。

当我想将控制器 C 推到顶部时,我想退回到 UINavigationController 附带的 默认 推送/弹出转换。为了实现这一点,我为

返回 nil
navigationController:animationControllerForOperation:fromViewController:toViewController:

但是如果你返回 nil,那么

navigationController:interactionControllerForAnimationController:

永远不会被调用,默认的“从左边缘平移”弹出交互过渡不起作用。

有没有办法返回默认的推送/弹出动画控制器和交互控制器? (id<UIViewControllerAnimatedTransitioning>id<UIViewControllerInteractiveTransitioning>有具体实现吗?)

还是其他方式?

【问题讨论】:

    标签: ios objective-c ios7


    【解决方案1】:

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

    也就是说,当您想要触发内置弹出手势时,您必须从此方法返回 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;
    }
    

    您可以查看sample project 以了解您的情况。视图控制器 A 和 B 之间的转换是自定义动画,带有自定义 B->A 弹出手势。视图控制器 B 和 C 之间的转换是默认的,带有内置导航控制器的弹出手势。

    希望这会有所帮助!

    【讨论】:

    • 根据 Apple 的 DTS 人员的说法,UINavigationController 附带的私有 interactivePopGestureRecognizer 在其委托中进行了许多检查,其中一些调用了私有 API。实现自己的委托并不能保证 100% 覆盖所有情况。
    • @Ziconic 案例?
    【解决方案2】:

    您需要在每次演示之前设置委托 - 例如在 prepareForSeque: 中。如果您想要自定义过渡,请将其设置为 self.如果你想要默认转换(如默认弹出转换),请将其设置为 nil。

    【讨论】:

    • 遗憾的是,这实际上是 Apple DTS 人员推荐的正确答案和方法,尽管它不是一个特别优雅的方法。基本上,您需要有 2 个 UINavigationControllerDelegate 对象,一个实现转换回调,一个不实现(或为零)。要获得默认的弹出转换,请使用不带回调的委托(或将委托设置为 nil)。要获得自定义转换,请将委托换成具有回调的委托(并在转换完成后恢复原始委托)。
    • 这仍然是推荐的方法吗?
    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

      在您完成自定义转换后,尝试将 (self.)navigationController.delegate 设置为 nil(或将其恢复为以前的值)。

      【讨论】:

        【解决方案5】:

        在您的手势识别器中,将委托(对您自己)设置在那里并返回您的动画和交互式过渡。返回交互式过渡时,请务必再次取消设置委托,以便其他所有内容继续使用默认过渡。

        我有一个working example on 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;
        }
        

        【讨论】:

          猜你喜欢
          • 2015-10-02
          • 1970-01-01
          • 2014-09-08
          • 2013-10-01
          • 1970-01-01
          • 1970-01-01
          • 2013-09-20
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多