我在我的应用程序中使用了 UIPageViewController,我想在其中有一些 UIButtons,有点像菜单。我遇到的问题是,当我将 UIButton(或任何其他交互式元素)放在屏幕边缘附近并点击它时,而不是应用 UIButton 操作,会发生页面更改(因为点击边缘屏幕更改 UIPageViewController 上的页面)。我想知道是否有办法使 UIButton 具有比 UIPageViewController 更高的优先级,这样当我点击按钮时,它会应用适当的操作而不是更改页面。
8 回答
我带着同样的问题来到这里。斯普利特的链接有答案。
使您的根视图控制器成为每个UIPageViewController
手势识别器的代表,然后防止触摸在任何内部发生时被传递UIControl
:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
return ([touch.view isKindOfClass:[UIControl class]] == NO);
}
UIPageViewController 有两个 UIGestureRecognizers。您可以通过 gestureRecognizers 属性访问它们。确定哪个是 UITapGestureRecognizer 然后使用它。希望这可以帮助。
对于只想复制/粘贴代码的人,这是我的:
// I don't want the tap on borders to change the page
-(void) desactivatePageChangerGesture {
for (UIGestureRecognizer* gestureRecognizer in self.pageViewController.gestureRecognizers) {
if ([gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]]) {
gestureRecognizer.enabled = NO;
}
}
}
只需在 UIPageViewController 创建后调用此函数。
从您的代码中注释掉这些行
self.view.gestureRecognizers = self.pageViewController.gestureRecognizers;
或按照 Split 的说明使用 UIGestureRecognizer
希望对你有帮助
我遇到了同样的问题,并且不确定如何处理 UIGestureRecognizer 委托方法。这个简短的示例假设您在 Xcode 4 中使用“基于页面的应用程序”项目类型。这是我所做的:
在
RootViewController.h
中,我确保宣布 RootViewController 将处理 UIGestureRecognizerDelegate 协议:@interface RootViewController : UIViewController <UIPageViewControllerDelegate, UIGestureRecognizerDelegate>
在
RootViewController.m
中,我将 RootViewController 指定为 UITapGestureRecognizer 的代表。这是在viewDidLoad
方法结束时完成的。我通过遍历每个gestureRecognizer 来查看哪个是UITapGestureRecognizer 来做到这一点。NSEnumerator *gestureLoop = [self.view.gestureRecognizers objectEnumerator]; id gestureRecognizer; while (gestureRecognizer = [gestureLoop nextObject]) { if ([gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]]) { [(UITapGestureRecognizer *)gestureRecognizer setDelegate:self]; } }
最后,我在底部添加了gestureRecognizer:shouldReceiveTouch方法
RootViewController.m
(这是直接从Split的链接复制的):- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { if ([touch.view isKindOfClass:[UIControl class]]) { // we touched a button, slider, or other UIControl return NO; // ignore the touch } return YES; // handle the touch }
旧答案:如果您UIPageViewController
有一个transitionStyle
ofUIPageViewControllerTransitionStyleScroll
并且您在 iOS 6.0+ 中,那么您不能使用该gestureRecognizer:shouldReceiveTouch:
方法,因为无法将委托设置为self
on,gestureRecognizers
因为pageViewController.gestureRecognizers
将返回 nil。有关更多信息,请参阅UIPageViewController 在 iOS 6 中不返回手势识别器。
如果您只是想确保UIPageViewController
将按钮触摸事件传递给 UIButton,您可以使用
for (UIScrollView *view in _pageViewController.view.subviews) {
if ([view isKindOfClass:[UIScrollView class]]) {
view.delaysContentTouches = NO;
}
}
如果您有transitionStyle
ofUIPageViewControllerTransitionStyleScroll
并且您使用的是 iOS 6.0+。
请参阅此答案,了解为什么在 a 中的delaysContentTouches = NO
某些情况下需要UIButton
UIScrollView
更新:在做了更多研究之后,如果您的问题是UIButton
click 似乎只是有时被调用,那么这实际上可能是 a 中所需的行为UIScrollView
。AUIScrollView
使用delaysContentTouches属性自动确定用户是尝试滚动还是尝试按下滚动视图内的按钮。我认为最好不要将此行为更改为默认值,NO
因为如果用户的手指放在按钮上,这样做将导致无法滚动。
在这里拦截 UIPageViewController 的点击手势识别器的解决方案都没有对我有用。我的目标是 iOS 8 和 9。
起作用的是在我的自定义按钮中覆盖函数touchesBegan
, touchesCancelled
,touchesMoved
和. 然后,如果触摸在我的自定义按钮的框架内开始和结束,我只需手动发送控制事件。touchesEnded
UIControl
.TouchUpInside
我不必为包含页面视图控制器或包含页面视图控制器的视图控制器做任何特别的事情。
Swift 5 answer here应该可以完成这项工作。
pageViewController.view.subviews.compactMap({ $0 as? UIScrollView }).first?.delaysContentTouches = false