UIPageViewController中的UIButton交互

问题描述 投票:11回答:8

我在我的应用程序中使用UIPageViewController,我想在其中有一些UIButtons,有点像菜单。我遇到的问题是,当我在屏幕边缘附近放置UIButton(或任何其他交互元素)并点击它时,而不是应用UIButton操作,会发生什么变化,页面会发生变化(因为边缘点击屏幕更改UIPageViewController上的页面)。我想知道是否有办法使UIButton具有比UIPageViewController更高的优先级,这样当我点击按钮时,它会应用相应的操作而不是更改页面。

iphone objective-c xcode uipageviewcontroller
8个回答
7
投票

我带着同样的问题来到这里。斯普利特的link有答案。

使您的根视图控制器成为每个UIPageViewController的手势识别器的委托,然后防止触摸被发送,如果它们发生在任何UIControl内:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
    return ([touch.view isKindOfClass:[UIControl class]] == NO);
}

4
投票

UIPageViewController有两个UIGestureRecognizer。您可以通过gestureRecognizers属性访问它们。确定哪一个是UITapGestureRecognizer,然后使用this.希望这有帮助。


2
投票

对于那些只想复制/粘贴代码的人来说,这是我的:

// 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后调用此函数。


1
投票

我遇到了同样的问题,并且不确定如何处理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 }

1
投票

从代码中注释掉这些行

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

或者按照Split的说法使用UIGestureRecognizer

希望对你有帮助


0
投票

老答案:如果你的UIPageViewControllertransitionStyleUIPageViewControllerTransitionStyleScroll并且你在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;
    }
}

如果你有transitionStyleUIPageViewControllerTransitionStyleScroll,你在iOS 6.0+。

请参阅this answer关于为什么在delaysContentTouches = NO中某些UIButton案例需要UIScrollView

更新:在做了一点研究之后,看起来如果你的问题是UIButton点击似乎只是有时被调用,那么这实际上可能是UIScrollView中所需的行为。 UIScrollView使用delaysContentTouches属性自动确定用户是否正在尝试滚动或尝试按滚动视图内的按钮。我认为最好不要将此行为更改为默认为NO,因为这样做会导致无法滚动,如果用户的手指在按钮上方。


0
投票

这里没有你拦截UIPageViewController的轻敲手势识别器的解决方案对我有用。我的目标是iOS 8和9。

有效的方法是在我的自定义按钮中覆盖touchesBegantouchesCancelledtouchesMovedtouchesEnded函数,这是UIControl的子类。然后我只是手动发送.TouchUpInside控件事件,如果触摸开始和结束在我的自定义按钮的框架内。

我没有必要为包含页面视图控制器或包含页面视图控制器的视图控制器做任何特殊操作。


0
投票

斯威夫特5回答这里应该做的工作。

pageViewController.view.subviews.compactMap({ $0 as? UIScrollView }).first?.delaysContentTouches = false

© www.soinside.com 2019 - 2024. All rights reserved.