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

时间:2022-08-26 22:48:30

iOS 7 has a great interactive animation for popping UIViewControllers. The transition is triggered by swiping from the left side of the screen but I would like to trigger the transition by swiping anywhere in my view controller. (I would also like to cancel the ones from the edge so I can use them for another custom transition...).

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

So far in my view controller I've added this in init. I know it's wrong, I'm not sure what I'm doing really.

到目前为止,在我的视图控制器中,我已经在init中添加了它。我知道这是错的,我不确定我在做什么。

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

How do I tie it to the built in interactivePopGestureRecognizer? Should that be done in my handleGesture: method?

如何将其与内置的interactivePopGestureRecognizer绑定?应该在我的handleGesture:方法中完成吗?

Edit: In Apple's documentation the word tie is actually used:

编辑:在Apple的文档中,实际使用了tie这个词:

interactivePopGestureRecognizer

The navigation controller installs this gesture recognizer on its view and uses it to pop the topmost view controller off the navigation stack. You can use this property to retrieve the gesture recognizer and tie it to the behavior of other gesture recognizers in your user interface. When tying your gesture recognizers together, make sure they recognize their gestures simultaneously to ensure that your gesture recognizers are given a chance to handle the event.

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

How do you tie to UIGestureRecognizers together?

你如何与UIGestureRecognizers结合在一起?

3 个解决方案

#1


1  

I think what the documentation means is that you can use that accessor to retrieve the navigation controller’s interactivePopGestureRecognizer for use in your own recognizers’ delegate callbacks. For example, in -gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:, you might want to return YES only if otherGestureRecognizer is the view controller’s interactive pop gesture recognizer.

我认为文档的含义是您可以使用该访问器来检索导航控制器的interactivePopGestureRecognizer,以便在您自己的识别器的委托回调中使用。例如,in -gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer :,如果otherGestureRecognizer是视图控制器的交互式弹出手势识别器,则可能只想返回YES。

#2


5  

Why interactivePopGestureRecognizer is worthless for this case

Gesture recognizers have two notification channels, the delegate and the target/action. The delegate is used for "should I even consider accepting this gesture" and this one does internal checks like:

手势识别器有两个通知通道,代表和目标/操作。该委托用于“我是否应该考虑接受此手势”,并且这个内部检查如下:

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
    return !self.isAnimating &&
           self.viewControllers.count > 1 &&
           !self.navigationBarHidden &&
           [self _doesTheNavigationControllerDelegateHaveCustomTransitions] &&
           [self _someOtherSecretJunk];
}

If the tests pass, it then calls the target/action which actually sets up and animates the interactive transition.

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

The only way to get the built-in pop interaction is for interactivePopGestureRecognizer to pass its delegate tests and call the action. If knew what the target/action were, we could try hooking that to your custom gesture like this:

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

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

But even then, Apple could have undocumented checks like:

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

- (void)_secretGestureRecognizerAction:(id)sender
{
    NSParameterAssert(sender == self.navigationController.interactiveGestureRecognizer);
    ...
}

What you can do

What you can do is a lot more complicated than you were probably hoping but has a lot more potential. You need to create your own interactive transition and attach it to your own gesture recognizer.

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

You're going to want to read tutorials and look at sample code on the subject, but the basic steps are:

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

  1. Create a subclass of UIPercentDrivenInteractiveTransition that conforms to UIViewControllerAnimatedTransitioning
  2. 创建符合UIViewControllerAnimatedTransitioning的UIPercentDrivenInteractiveTransition的子类

  3. Implement animateTransition: in a way that matches the appearance of the default transition (or your own design).
  4. 实现animateTransition:以与默认转换(或您自己的设计)的外观匹配的方式。

  5. Create a class that conforms to UINavigationControllerDelegate and implement the animation methods as well as a method for handling the gesture recognizer.
  6. 创建一个符合UINavigationControllerDelegate的类并实现动画方法以及处理手势识别器的方法。

  7. Set up the navigation controller to use that delegate, add the gesture recognizer to your view controller with that class handling target/action and delegate methods.
  8. 设置导航控制器以使用该委托,使用该类处理目标/操作和委托方法将手势识别器添加到视图控制器。

It's important to note that once you add your own custom transitions, interactivePopGestureRecognizer effectively dies and the standard interactions cease to work so you'll need to do your custom stuff everywhere.

重要的是要注意,一旦你添加了自己的自定义过渡,interactivePopGestureRecognizer就会有效地消失,标准的交互也会停止工作,所以你需要在任何地方都做自定义的事情。

#3


0  

What I've done is this:

我做的是这样的:

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

Whether or not Apple approves of such a use of KVC in App Store apps remains to be seen. It does work, however, so apparently no undocumented runtime checking is taking place.

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

#1


1  

I think what the documentation means is that you can use that accessor to retrieve the navigation controller’s interactivePopGestureRecognizer for use in your own recognizers’ delegate callbacks. For example, in -gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:, you might want to return YES only if otherGestureRecognizer is the view controller’s interactive pop gesture recognizer.

我认为文档的含义是您可以使用该访问器来检索导航控制器的interactivePopGestureRecognizer,以便在您自己的识别器的委托回调中使用。例如,in -gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer :,如果otherGestureRecognizer是视图控制器的交互式弹出手势识别器,则可能只想返回YES。

#2


5  

Why interactivePopGestureRecognizer is worthless for this case

Gesture recognizers have two notification channels, the delegate and the target/action. The delegate is used for "should I even consider accepting this gesture" and this one does internal checks like:

手势识别器有两个通知通道,代表和目标/操作。该委托用于“我是否应该考虑接受此手势”,并且这个内部检查如下:

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
    return !self.isAnimating &&
           self.viewControllers.count > 1 &&
           !self.navigationBarHidden &&
           [self _doesTheNavigationControllerDelegateHaveCustomTransitions] &&
           [self _someOtherSecretJunk];
}

If the tests pass, it then calls the target/action which actually sets up and animates the interactive transition.

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

The only way to get the built-in pop interaction is for interactivePopGestureRecognizer to pass its delegate tests and call the action. If knew what the target/action were, we could try hooking that to your custom gesture like this:

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

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

But even then, Apple could have undocumented checks like:

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

- (void)_secretGestureRecognizerAction:(id)sender
{
    NSParameterAssert(sender == self.navigationController.interactiveGestureRecognizer);
    ...
}

What you can do

What you can do is a lot more complicated than you were probably hoping but has a lot more potential. You need to create your own interactive transition and attach it to your own gesture recognizer.

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

You're going to want to read tutorials and look at sample code on the subject, but the basic steps are:

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

  1. Create a subclass of UIPercentDrivenInteractiveTransition that conforms to UIViewControllerAnimatedTransitioning
  2. 创建符合UIViewControllerAnimatedTransitioning的UIPercentDrivenInteractiveTransition的子类

  3. Implement animateTransition: in a way that matches the appearance of the default transition (or your own design).
  4. 实现animateTransition:以与默认转换(或您自己的设计)的外观匹配的方式。

  5. Create a class that conforms to UINavigationControllerDelegate and implement the animation methods as well as a method for handling the gesture recognizer.
  6. 创建一个符合UINavigationControllerDelegate的类并实现动画方法以及处理手势识别器的方法。

  7. Set up the navigation controller to use that delegate, add the gesture recognizer to your view controller with that class handling target/action and delegate methods.
  8. 设置导航控制器以使用该委托,使用该类处理目标/操作和委托方法将手势识别器添加到视图控制器。

It's important to note that once you add your own custom transitions, interactivePopGestureRecognizer effectively dies and the standard interactions cease to work so you'll need to do your custom stuff everywhere.

重要的是要注意,一旦你添加了自己的自定义过渡,interactivePopGestureRecognizer就会有效地消失,标准的交互也会停止工作,所以你需要在任何地方都做自定义的事情。

#3


0  

What I've done is this:

我做的是这样的:

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

Whether or not Apple approves of such a use of KVC in App Store apps remains to be seen. It does work, however, so apparently no undocumented runtime checking is taking place.

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