ios UIPageViewController 手势识别器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7788780/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 21:53:45  来源:igfitidea点击:

UIPageViewController Gesture recognizers

iosuigesturerecognizer

提问by Rich86man

I have a UIPageViewController load with my Viewcontroller.

我的 Viewcontroller 有一个 UIPageViewController 负载。

The view controllers have buttons which are overridden by the PageViewControllers gesture recognizers.

视图控制器具有被 PageViewControllers 手势识别器覆盖的按钮。

For example I have a button on the right side of the viewcontroller and when you press the button, the PageViewController takes over and changes the page.

例如,我在视图控制器的右侧有一个按钮,当您按下按钮时,PageViewController 会接管并更改页面。

How can I make the button receive the touch and cancel the gesture recognizer in the PageViewController?

如何让按钮接收触摸并取消 PageViewController 中的手势识别器?

I think the PageViewController makes my ViewController a subview of its view.

我认为 PageViewController 使我的 ViewController 成为其视图的子视图。

I know I could turn off all of the Gestures, but this isn't the effect I'm looking for.

我知道我可以关闭所有手势,但这不是我想要的效果。

I would prefernot to subclass the PageViewController as apple says this class is not meant to be subclassed.

我会更喜欢苹果说这个类并不意味着子类没有子类PageViewController。

采纳答案by jramer

You can override

你可以覆盖

-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
 shouldReceiveTouch:(UITouch *)touch

to better control when the PageViewController should receive the touch and not. Look at "Preventing Gesture Recognizers from Analyzing Touches" in Dev API Gesture Recognizers

更好地控制 PageViewController 何时应该接收触摸而不是。查看Dev API Gesture Recognizers 中的“Preventing Gesture Recognizers from Analyzing Touches”

My solution looks like this in the RootViewController for the UIPageViewController:

我的解决方案在 UIPageViewController 的 RootViewController 中如下所示:

In viewDidLoad:

在 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;
}

The override:

覆盖:

-(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;
}

And don't forget to set the RootViewController as UIGestureRecognizerDelegate.

并且不要忘记将 RootViewController 设置为 UIGestureRecognizerDelegate。

(FYI, I'm only in Landscape mode.)

(仅供参考,我只处于横向模式。)

EDIT - The above code translated into Swift 2:

编辑 - 上面的代码翻译成 Swift 2:

In viewDidLoad:

在 viewDidLoad 中:

for gr in self.view.gestureRecognizers! {
    gr.delegate = self
}

Make the page view controller inherit UIGestureRecognizerDelegatethen add:

使页面视图控制器继承UIGestureRecognizerDelegate然后添加:

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
}

回答by Pat McG

Here is another solution, which can be added in the viewDidLoadtemplate right after the self.view.gestureRecognizers = self.pageViewController.gestureRecognizerspart from the Xcode template. It avoids messing with the guts of the gesture recognizers or dealing with its delegates. It just removes the tap gesture recognizer from the views, leaving only the swipe recognizer.

这是另一种解决方案,可以在 Xcode 模板中viewDidLoadself.view.gestureRecognizers = self.pageViewController.gestureRecognizers部分之后立即添加到模板中。它避免了与手势识别器的内部混乱或与它的代表打交道。它只是从视图中删除了点击手势识别器,只留下滑动识别器。

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];
}

Now to switch between pages, you have to swipe. Taps now only work on your controls on top of the page view (which is what I was after).

现在要在页面之间切换,您必须滑动。Taps 现在只适用于页面视图顶部的控件(这是我所追求的)。

回答by Phillip

I had the same problem. The sample and documentation does this in loadView or viewDidLoad:

我有同样的问题。示例和文档在 loadView 或 viewDidLoad 中执行此操作:

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

This replaces the gesture recognizers from the UIViewControllers views with the gestureRecognizers of the UIPageViewController. Now when a touch occurs, they are first sent through the pageViewControllers gesture recognizers - if they do not match, they are sent to the subviews.

这将 UIViewControllers 视图中的手势识别器替换为 UIPageViewController 的gestureRecognizers。现在当触摸发生时,它们首先通过 pageViewControllers 手势识别器发送 - 如果它们不匹配,它们将被发送到子视图。

Just uncomment that line, and everything is working as expected.

只需取消注释该行,一切都按预期工作。

Phillip

菲利普

回答by noRema

Setting the gestureRecognizers delegate to a viewController as below no longer work on ios6

如下所示将gestureRecognizers 委托设置为viewController 不再适用于ios6

for (UIGestureRecognizer *gR in self.view.gestureRecognizers) {
    gR.delegate = self;
}

In ios6, setting your pageViewController's gestureRecognizers delegate to a viewController causes a crash

在 ios6 中,将 pageViewController 的gestureRecognizers 委托设置为viewController 会导致崩溃

回答by Hunter Monk

In newer versions (I am in Xcode 7.3 targeting iOS 8.1+), none of these solutions seem to work.

在较新的版本中(我使用的是针对 iOS 8.1+ 的 Xcode 7.3),这些解决方案似乎都不起作用。

The accepted answer would crash with error:

接受的答案会因错误而崩溃:

UIScrollView's built-in pan gesture recognizer must have its scroll view as its delegate.

UIScrollView 的内置平移手势识别器必须将其滚动视图作为其委托。

The currently highest ranking answer (from Pat McG) no longer works as well because UIPageViewController's scrollview seems to be using odd gesture recognizer sub classes that you can't check for. Therefore, the statement if ( [recognizer isKindOfClass:[UITapGestureRecognizer class]] )never executes.

当前排名最高的答案(来自 Pat McG)不再有效,因为UIPageViewController的滚动视图似乎使用了您无法检查的奇怪手势识别器子类。因此,该语句if ( [recognizer isKindOfClass:[UITapGestureRecognizer class]] )永远不会执行。

I chose to just set cancelsTouchesInView on each recognizer to false, which allows subviews of the UIPageViewControllerto receive touches as well.

我选择只将每个识别器上的 cancelsTouchesInView 设置为 false,这也允许子视图UIPageViewController接收触摸。

In viewDidLoad:

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
}

回答by Leto Baxevanaki

In my case I wanted to disable tapping on the UIPageControl and let tapping being received by another button on the screen. Swipe still works. I have tried numerous ways and I believe that was the simplest working solution:

在我的情况下,我想禁用点击 UIPageControl 并让点击被屏幕上的另一个按钮接收。滑动仍然有效。我尝试了很多方法,我相信这是最简单的工作解决方案:

for (UIPageControl *view in _pageController.view.subviews) {
    if ([view isKindOfClass:[UIPageControl class]]) {
        view.enabled = NO;
    }
}

This is getting the UIPageControl view from the UIPageController subviews and disabling user interaction.

这是从 UIPageController 子视图获取 UIPageControl 视图并禁用用户交互。

回答by Adam Johns

I used

我用了

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

to allow clicks to go through to buttons inside a UIPageViewController

允许点击进入 UIPageViewController 内的按钮

回答by tdf

Just create a subview (linked to a new IBOutlet gesturesView) in your RootViewController and assign the gestures to this new view. This view cover the part of the screen you want the gesture enable.

只需在您的 RootViewController 中创建一个子视图(链接到一个新的 IBOutlet 手势视图)并将手势分配给这个新视图。此视图覆盖了您希望启用手势的屏幕部分。

in viewDidLoad change :

在 viewDidLoad 更改:

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

to :

到 :

self.gesturesView.gestureRecognizers = self.pageViewController.gestureRecognizers;

回答by Ryan Heitner

This is the solution which worked best for me I tried JRAMER answer with was fine except I would get an Error when paging beyond the bounds (page -1 or page 23 for me)

这是最适合我的解决方案我尝试过 JRAMER 答案很好,除非我在超出范围的分页时出现错误(对我来说是第 -1 页或第 23 页)

PatMCG solution did not give me enough flexibility since it cancelled all the taprecognizers, I still wanted the tap but not within my label

PatMCG 解决方案没有给我足够的灵活性,因为它取消了所有的 Taprecognizer,我仍然想要水龙头,但不在我的标签内

In my UILabel I simply overrode as follows, this cancelled tap for my label only

在我的 UILabel 中,我只是按如下方式覆盖,这仅取消了我的标签的点击

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
 if ([gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]]) {
     return NO;
 } else {
     return YES;
 }
}

回答by Bill Cheswick

I create pageviewcontrollers regularly as my user jumps, curls, and slides to various different page views. In the routine that creates a new pageviewcontroller, I use a slightly simpler version of the excellent code shown above:

当我的用户跳转、卷曲和滑动到各种不同的页面视图时,我会定期创建 pageviewcontrollers。在创建新 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;
    }
}

Now the taps work as I wish (with left and right taps jumping a page, and the curls work fine.

现在水龙头按我的意愿工作(左右水龙头跳页,卷发工作正常。