我在我的应用程序中使用UIPageViewController,我想在其中有一些UIButtons,有点像菜单。我遇到的问题是,当我在屏幕边缘附近放置UIButton(或任何其他交互元素)并点击它时,而不是应用UIButton操作,会发生什么变化,页面会发生变化(因为边缘点击屏幕更改UIPageViewController上的页面)。我想知道是否有办法使UIButton具有比UIPageViewController更高的优先级,这样当我点击按钮时,它会应用相应的操作而不是更改页面。
我带着同样的问题来到这里。斯普利特的link有答案。
使您的根视图控制器成为每个UIPageViewController
的手势识别器的委托,然后防止触摸被发送,如果它们发生在任何UIControl
内:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
return ([touch.view isKindOfClass:[UIControl class]] == NO);
}
UIPageViewController有两个UIGestureRecognizer。您可以通过gestureRecognizers属性访问它们。确定哪一个是UITapGestureRecognizer,然后使用this.希望这有帮助。
对于那些只想复制/粘贴代码的人来说,这是我的:
// 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后调用此函数。
我遇到了同样的问题,并且不确定如何处理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];
}
}
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
}
从代码中注释掉这些行
self.view.gestureRecognizers = self.pageViewController.gestureRecognizers;
或者按照Split的说法使用UIGestureRecognizer
希望对你有帮助
老答案:如果你的UIPageViewController
有transitionStyle
的UIPageViewControllerTransitionStyleScroll
并且你在iOS 6.0+,那么你不能使用gestureRecognizer:shouldReceiveTouch:
方法,因为没有办法在self
上设置委托给gestureRecognizers
,因为pageViewController.gestureRecognizers
将返回nil。有关详细信息,请参阅UIPageViewController returns no Gesture Recognizers in iOS 6。
如果你只是想确保你的UIPageViewController
将按钮触摸事件传递给UIButton,你可以使用
for (UIScrollView *view in _pageViewController.view.subviews) {
if ([view isKindOfClass:[UIScrollView class]]) {
view.delaysContentTouches = NO;
}
}
如果你有transitionStyle
的UIPageViewControllerTransitionStyleScroll
,你在iOS 6.0+。
请参阅this answer关于为什么在delaysContentTouches = NO
中某些UIButton
案例需要UIScrollView
更新:在做了一点研究之后,看起来如果你的问题是UIButton
点击似乎只是有时被调用,那么这实际上可能是UIScrollView
中所需的行为。 UIScrollView
使用delaysContentTouches属性自动确定用户是否正在尝试滚动或尝试按滚动视图内的按钮。我认为最好不要将此行为更改为默认为NO
,因为这样做会导致无法滚动,如果用户的手指在按钮上方。
这里没有你拦截UIPageViewController的轻敲手势识别器的解决方案对我有用。我的目标是iOS 8和9。
有效的方法是在我的自定义按钮中覆盖touchesBegan
,touchesCancelled
,touchesMoved
和touchesEnded
函数,这是UIControl
的子类。然后我只是手动发送.TouchUpInside
控件事件,如果触摸开始和结束在我的自定义按钮的框架内。
我没有必要为包含页面视图控制器或包含页面视图控制器的视图控制器做任何特殊操作。
斯威夫特5回答这里应该做的工作。
pageViewController.view.subviews.compactMap({ $0 as? UIScrollView }).first?.delaysContentTouches = false