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) } } }