UIPageViewController手势识别器

我一直在申请一段时间,但是由于NDA,我不能问这个问题。

我有一个UIPageViewController加载我的Viewcontroller。 视图控制器具有由PageViewControllers手势识别器覆盖的button。 例如,我在viewcontroller的右侧有一个button,当你按下button时,PageViewController接pipe并改变页面。

我如何使button接收触摸并取消PageViewController中的手势识别器?

我认为PageViewController使得我的ViewController成为其视图的子视图。

我知道我可以关掉所有的手势,但这不是我要找的效果。

我不希望子类的PageViewController作为苹果说,这个类不打算分类。

你可以覆盖

 -(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch 

以更好地控制PageViewController何时应该接收触摸而不是。 请参阅Dev API手势识别器中的 “防止手势识别器分析触摸”

我的解决scheme如下所示在UIPageViewController的RootViewController中:

在viewDidLoad中:

 //EDITED Need to take care of all gestureRecogizers. Got a bug when only setting the delegate for Tap for (UIGestureRecognizer *gR in self.view.gestureRecognizers) { gR.delegate = self; } 

覆盖:

 -(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { //Touch gestures below top bar should not make the page turn. //EDITED Check for only Tap here instead. if ([gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]]) { CGPoint touchPoint = [touch locationInView:self.view]; if (touchPoint.y > 40) { return NO; } else if (touchPoint.x > 50 && touchPoint.x < 430) {//Let the buttons in the middle of the top bar receive the touch return NO; } } return YES; } 

不要忘记将RootViewController设置为UIGestureRecognizerDelegate。

(仅供参考,我只处于横向模式。)

编辑 – 上面的代码翻译成Swift 2:

在viewDidLoad中:

 for gr in self.view.gestureRecognizers! { gr.delegate = self } 

使页面视图控制器inheritanceUIGestureRecognizerDelegate然后添加:

 func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool { if let _ = gestureRecognizer as? UITapGestureRecognizer { let touchPoint = touch .locationInView(self.view) if (touchPoint.y > 40 ){ return false }else{ return true } } return true } 

这里是另一个解决scheme,它可以在Xcode模板中的self.view.gestureRecognizers = self.pageViewController.gestureRecognizers部分后面的viewDidLoad模板中添加。 它避免了与姿态识别器的胆量混淆或与其代表打交道。 它只是从视图中删除轻拍手势识别器,只留下轻扫识别器。

 self.view.gestureRecognizers = self.pageViewController.gestureRecognizers; // Find the tap gesture recognizer so we can remove it! UIGestureRecognizer* tapRecognizer = nil; for (UIGestureRecognizer* recognizer in self.pageViewController.gestureRecognizers) { if ( [recognizer isKindOfClass:[UITapGestureRecognizer class]] ) { tapRecognizer = recognizer; break; } } if ( tapRecognizer ) { [self.view removeGestureRecognizer:tapRecognizer]; [self.pageViewController.view removeGestureRecognizer:tapRecognizer]; } 

现在要切换页面,你必须滑动。 现在的水龙头只能在页面视图顶部的控件上工作(这就是我以前的做法)。

我有同样的问题。 示例和文档在loadView或viewDidLoad中执行此操作:

 self.view.gestureRecognizers = self.pageViewController.gestureRecognizers; 

这将使用UIPageViewController的gestureRecognizersreplaceUIViewControllers视图中的手势识别器。 现在,当触摸发生时,它们首先通过pageViewControllers手势识别器发送 – 如果它们不匹配,则发送到子视图。

只要取消注释,一切都按预期工作。

菲利普

如下所示将gestureRecognizers委托设置为viewController不再适用于ios6

 for (UIGestureRecognizer *gR in self.view.gestureRecognizers) { gR.delegate = self; } 

在ios6中,将您的pageViewController的gestureRecognizers委托设置为viewController会导致崩溃

在较新的版本(我在Xcode 7.3中定位iOS 8.1+),这些解决scheme似乎没有工作。

接受的答案会崩溃,错误:

UIScrollView的内置平移手势识别器必须将其滚动视图作为其代表。

当前排名最高的答案(来自Pat McG)不再适用,因为UIPageViewController的滚动视图似乎使用了无法检查的奇数手势识别器子类。 因此,语句if ( [recognizer isKindOfClass:[UITapGestureRecognizer class]] )从不执行。

我select将每个识别器上的cancelsTouchesInView设置为false,这允许UIPageViewController子视图也可以接收触摸。

viewDidLoad

 guard let recognizers = self.pageViewController.view.subviews[0].gestureRecognizers else { print("No gesture recognizers on scrollview.") return } for recognizer in recognizers { recognizer.cancelsTouchesInView = false } 

我用了

 for (UIScrollView *view in _pageViewController.view.subviews) { if ([view isKindOfClass:[UIScrollView class]]) { view.delaysContentTouches = NO; } } 

允许点击进入UIPageViewController中的button

如果您使用的是一个button,您可以重写touchesBegan,touchesMoved和touchesEnded,根据需要调用自己的编程页面,但不能调用super,并将通知传递给通知链。

也可以用这个(谢谢帮忙,跟一下委托):

 // add UIGestureRecognizerDelegate NSPredicate *tp = [NSPredicate predicateWithFormat:@"self isKindOfClass: %@", [UITapGestureRecognizer class]]; UITapGestureRecognizer *tgr = (UITapGestureRecognizer *)[self.pageViewController.view.gestureRecognizers filteredArrayUsingPredicate:tp][0]; tgr.delegate = self; // tap delegating NSPredicate *pp = [NSPredicate predicateWithFormat:@"self isKindOfClass: %@", [UIPanGestureRecognizer class]]; UIPanGestureRecognizer *pgr = (UIPanGestureRecognizer *)[self.pageViewController.view.gestureRecognizers filteredArrayUsingPredicate:pp][0]; pgr.delegate = self; // pan delegating - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { CGPoint touchPoint = [touch locationInView:self.view]; if (UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation]) && touchPoint.y > 915 ) { return NO; // if y > 915 px in portrait mode } if (UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]) && touchPoint.y > 680 ) { return NO; // if y > 680 px in landscape mode } return YES; } 

为我完美的工作:)

这是最适合我的解决scheme我试着JRAMER回答很好,除非我会得到一个错误,当分页超出界限(页面-1或页面23对我来说)

PatMCG解决scheme没有给我足够的灵活性,因为它取消了所有的taprecognizers,我仍然想要tap,但不在我的标签内

在我的UILabel我简单地覆盖如下,这只取消了我的标签轻拍

 - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer { if ([gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]]) { return NO; } else { return YES; } } 

当我的用户跳转,curl和幻灯片到各种不同的页面视图时,我会定期创buildpageviewcontrollers。 在创build一个新的pageviewcontroller的例程中,我使用上面显示的一个稍微简单的优秀代码版本:

 UIPageViewController *npVC = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStylePageCurl navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options: options]; ... // Find the pageView tap gesture recognizer so we can remove it! for (UIGestureRecognizer* recognizer in npVC.gestureRecognizers) { if ( [recognizer isKindOfClass:[UITapGestureRecognizer class]] ) { UIGestureRecognizer* tapRecognizer = recognizer; [npVC.view removeGestureRecognizer:tapRecognizer]; break; } } 

现在水龙头正常工作(左右水龙头跳页,卷发工作正常。

只需在您的RootViewController中创build一个子视图(链接到一个新的IBOutlet手势视图),并将手势分配给这个新的视图。 此视图覆盖了您希望手势启用的部分屏幕。

在viewDidLoad中更改:

 self.view.gestureRecognizers = self.pageViewController.gestureRecognizers; 

至 :

 self.gesturesView.gestureRecognizers = self.pageViewController.gestureRecognizers; 

在我的情况下,我想禁用攻丝的UIPageControl,并让点击被屏幕上的另一个button接收。 刷卡仍然有效。 我尝试了很多方法,我相信这是最简单的工作解决scheme:

 for (UIPageControl *view in _pageController.view.subviews) { if ([view isKindOfClass:[UIPageControl class]]) { view.enabled = NO; } } 

这是从UIPageController子视图获取UIPageControl视图并禁用用户交互。

Swift 3扩展删除水龙头识别器:

  import UIKit extension UIPageViewController { func removeTapRecognizer() { let gestureRecognizers = self.gestureRecognizers var tapGesture: UIGestureRecognizer? gestureRecognizers.forEach { recognizer in if recognizer.isKind(of: UITapGestureRecognizer.self) { tapGesture = recognizer } } if let tapGesture = tapGesture { self.view.removeGestureRecognizer(tapGesture) } } }