如何从自定义 UIGestureRecognizer 触发 NavigationController 的 interactivePopGestureRecognizer

Posted

技术标签:

【中文标题】如何从自定义 UIGestureRecognizer 触发 NavigationController 的 interactivePopGestureRecognizer【英文标题】:How can I trigger a NavigationController's interactivePopGestureRecognizer from a custom UIGestureRecognizer 【发布时间】:2014-01-10 16:12:21 【问题描述】:

ios 7 为弹出 UIViewControllers 提供了很棒的交互式动画。过渡是通过从屏幕左侧滑动触发的,但我想通过在视图控制器中的任意位置滑动来触发过渡。 (我还想从边缘取消那些,以便我可以将它们用于另一个自定义过渡......)。

到目前为止,在我的视图控制器中,我已将其添加到 init。我知道这是错的,我不确定自己到底在做什么。

UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture:)];
panRecognizer.delegate = self.navigationController.interactivePopGestureRecognizer.delegate;
[self.view addGestureRecognizer:panRecognizer];

如何将它与内置的 interactivePopGestureRecognizer 联系起来?应该在我的handleGesture: 方法中完成吗?

编辑:在Apple's documentation中实际使用了tie这个词:

interactivePopGestureRecognizer

导航控制器在其视图上安装此手势识别器,并使用它从导航堆栈中弹出最顶层的视图控制器。您可以使用此属性来检索手势识别器并将其与用户界面中其他手势识别器的行为联系起来。将您的手势识别器绑定在一起时,请确保它们同时识别自己的手势,以确保您的手势识别器有机会处理事件。

你如何将 UIGestureRecognizers 绑定在一起?

【问题讨论】:

【参考方案1】:

为什么interactivePopGestureRecognizer在这种情况下一文不值

手势识别器有两个通知通道,委托和目标/动作。委托用于“我是否应该考虑接受这个手势”,这个委托进行内部检查,例如:

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer

    return !self.isAnimating &&
           self.viewControllers.count > 1 &&
           !self.navigationBarHidden &&
           [self _doesTheNavigationControllerDelegateHaveCustomTransitions] &&
           [self _someOtherSecretJunk];

如果测试通过,它会调用实际设置并动画交互过渡的目标/动作。

获得内置弹出交互的唯一方法是让interactivePopGestureRecognizer 通过其委托测试并调用操作。如果知道目标/动作是什么,我们可以尝试将其与您的自定义手势挂钩,如下所示:

[[UIPanGestureRecognizer alloc] 
    initWithTarget:self.navigationController._secretGestureRecognizerTarget 
            action:@selector(_secretGestureRecognizerAction:)];

但即便如此,Apple 也可能会进行无证检查,例如:

- (void)_secretGestureRecognizerAction:(id)sender

    NSParameterAssert(sender == self.navigationController.interactiveGestureRecognizer);
    ...

你能做什么

您可以做的事情比您可能希望的要复杂得多,但潜力更大。您需要创建自己的交互式过渡并将其附加到您自己的手势识别器。

您会想要阅读教程并查看有关该主题的示例代码,但基本步骤是:

    创建符合UIViewControllerAnimatedTransitioning 的UIPercentDrivenInteractiveTransition 的子类 以与默认过渡(或您自己的设计)外观相匹配的方式实现 animateTransition:。 创建一个符合 UINavigationControllerDelegate 的类并实现动画方法以及处理手势识别器的方法。 设置导航控制器以使用该委托,使用该类处理目标/动作和委托方法将手势识别器添加到您的视图控制器。

请务必注意,一旦您添加了自己的自定义过渡,interactivePopGestureRecognizer 就会有效地消失,并且标准交互停止工作,因此您需要在任何地方进行自定义操作。

【讨论】:

【参考方案2】:

我认为文档的意思是您可以使用该访问器来检索导航控制器的 interactivePopGestureRecognizer 以用于您自己的识别器的委托回调。例如,在 -gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer: 中,您可能希望仅在 otherGestureRecognizer 是视图控制器的交互式弹出手势识别器时返回 YES

【讨论】:

最后我禁用了 Apple 的 interactivePopGestureRecognizer 并在我的 viewController 堆栈中实现了我自己的更高层。不过 Zev 是正确的,如果我仍然使用识别器,我绝对可以在委托方法中使用这个访问器来控制触发的内容和时间。【参考方案3】:

我所做的是这样的:

[[_myCustomRecogniser mutableArrayValueForKey:@"targets"] addObjectsFromArray:[self.navigationController.interactivePopGestureRecognizer valueForKey:@"targets"]];

Apple 是否批准在 App Store 应用程序中使用这种 KVC 仍有待观察。但是,它确实有效,因此显然没有进行未记录的运行时检查。

【讨论】:

以上是关于如何从自定义 UIGestureRecognizer 触发 NavigationController 的 interactivePopGestureRecognizer的主要内容,如果未能解决你的问题,请参考以下文章

如何从自定义列表视图中获取选定项目并在 toast 消息中打印?

如何从自定义反应挂钩访问数据

如何从自定义 UIView 类调用函数?

如何从自定义 UITextView 单元中获取文本?

如何判断 UITabBar 是不是从自定义视图打开?

如何从自定义模块中正确导入函数