UIButton在UIPageViewController中的交互



我在我的应用程序中使用一个UIPageViewController我想在它里面有一些uibutton,有点像一个菜单。我的问题是,当我把一个UIButton(或任何其他交互元素)靠近屏幕的边缘,点击它,而不是UIButton动作被应用,发生的是页面改变(因为在屏幕的边缘点击改变页面在UIPageViewController)。我想知道是否有一种方法可以使UIButton具有比UIPageViewController更高的优先级,以便当我点击按钮时,它应用适当的动作而不是改变页面。

我也是带着同样的问题来的。Split的链接有答案

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

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

UIPageViewController有两个uigesturerecognizer。你可以通过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创建后调用这个函数

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

从代码中注释掉这些行

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

或者按照Split

的指示使用UIGestureRecognizer

希望对你有帮助

旧答案:如果你的UIPageViewControllerUIPageViewControllerTransitionStyleScrolltransitionStyle,你是在iOS 6.0+,那么你不能使用gestureRecognizer:shouldReceiveTouch:方法,因为没有办法将gestureRecognizers上的委托设置为self,因为pageViewController.gestureRecognizers将返回nil。关于这一点的更多信息,请参阅iOS 6中的UIPageViewController返回no Gesture Recognizers。

如果你只是想确保你的UIPageViewController将按钮触摸事件传递给UIButton,你可以使用

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

如果你的transitionStyleUIPageViewControllerTransitionStyleScroll是iOS 6.0+,

参见UIScrollViewUIButton的某些情况下为什么需要delaysContentTouches = NO的答案

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

这里拦截UIPageViewController的点击手势识别器的解决方案都不适合我。我的目标是iOS 8和iOS 9。

工作是覆盖功能touchesBegan, touchesCancelled, touchesMovedtouchesEnded在我的自定义按钮,这是UIControl的子类。然后,如果触摸在我的自定义按钮的框架内开始和结束,我只需手动发送.TouchUpInside控制事件。

我不需要为包含页面视图控制器或包含页面视图控制器的视图控制器做任何特别的事情

快速回答这里应该可以完成工作。

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

最新更新