UIScrollView 只能用一根手指滚动

Posted

技术标签:

【中文标题】UIScrollView 只能用一根手指滚动【英文标题】:UIScrollView scrolling only with one finger 【发布时间】:2015-03-13 11:42:49 【问题描述】:

ios7 和 iOS8

我需要在UIScrollview 中禁用两指或三指滚动。

我试过了:

[self.scrollView.panGestureRecognizer setMaximumNumberOfTouches:1];
[self.scrollView.panGestureRecognizer setMinimumNumberOfTouches:1];

但它没有效果。仍然可以用两根手指滚动。

如果我尝试将 max 和 min 设置为 2。一个手指滚动被禁用但 3 个手指滚动可能:(

我也试过了,但没有成功:

for (UIGestureRecognizer* pan in self.scrollView.gestureRecognizers) 
        OTTNSLog(@"touches: %ld", (unsigned long)pan.numberOfTouches);
        if ([pan isKindOfClass:[UIPanGestureRecognizer class]])
        
            UIPanGestureRecognizer *mpanGR = (UIPanGestureRecognizer *) pan;
            mpanGR.minimumNumberOfTouches = 1;
            mpanGR.maximumNumberOfTouches = 1;

        

        if ([pan isKindOfClass:[UISwipeGestureRecognizer class]])
        
            UISwipeGestureRecognizer *mswipeGR = (UISwipeGestureRecognizer *) pan;
            mswipeGR.numberOfTouchesRequired = 1;
        

    

有人知道,它是如何解决这个问题的吗?

谢谢。

【问题讨论】:

此链接可能会有所帮助:***.com/questions/8210614/… 【参考方案1】:

问题:

UIPanGestureRecognizerUIScrollView 的底层时 - 不幸的是,这也会影响 UIPageViewController - maximumNumberOfTouches 的行为不符合预期,minimumNumberOfTouches 但始终正确限制下限。

在监控这些参数时,它们会报告正确的值 - 它们似乎在做自己的工作 - 只是 UIScrollView 本身不尊重它们并忽略它们的设置!


解决方案:

minimumNumberOfTouches 设置为所需的值,例如1 和 - 非常重要 - maximumNumberOfTouches 到 2 !!!

myScrollView.panGestureRecognizer.minimumNumberOfTouches = 1;
myScrollView.panGestureRecognizer.maximumNumberOfTouches = 2;

在你的 scrollView 的 @interface 声明中遵守 UIGestureRecognizerDelegate 协议。您不必为UIScrollView 设置panGestureRecognizer.delegate!!!!委托已经设置,因为UIScrollView 需要是它自己的pan/pinchGestureRecognizer 的委托。

然后实现UIGestureRecognizer委托方法:

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer 

    NSLog(@"%d", gestureRecognizer.numberOfTouches);
    NSLog(@"%@", gestureRecognizer.description);

        if (gestureRecognizer == self.panGestureRecognizer) 
            if (gestureRecognizer.numberOfTouches > 1) 
                return NO;
             else 
                return YES;
            
         else 
            return YES;
        
    


更安全的版本:

如果您有一个自定义的 scrollView 类并且想要非常安全,您还可以再添加一行代码来消除与其他 scrollView 的歧义:


- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer 

    NSLog(@"%d", gestureRecognizer.numberOfTouches);
    NSLog(@"%@", gestureRecognizer.description);

    if ([gestureRecognizer.view isMemberOfClass:[MY_CustomcrollView class]]) 
        if (gestureRecognizer == self.panGestureRecognizer) 
            if (gestureRecognizer.numberOfTouches > 1) 
                return NO;
             else 
                return YES;
            
         else 
            return YES;
        
     else 
        return YES;
    


附加信息:

NSLog 告诉您触摸的次数。如果您将 minmax 设置为相同的值(如上例中的 1),则 @ 987654338@ 永远不会被触发... ;-)

这就是为什么 maximumNumberOfTouches 必须至少是 minimumNumberOfTouches + 1

panGestureRecognizer.minimumNumberOfTouches = 1;
panGestureRecognizer.maximumNumberOfTouches = minimumNumberOfTouches + 1;

极客部分:

for (UIView *view in self.view.subviews) 
    if ([view isKindOfClass:[UIScrollView class]]) 
        NSLog(@"myPageViewController - SCROLLVIEW GESTURE RECOGNIZERS: %@", view.gestureRecognizers.description);
        ((UIPanGestureRecognizer *)view.gestureRecognizers[1]).minimumNumberOfTouches = 1;
        ((UIPanGestureRecognizer *)view.gestureRecognizers[1]).maximumNumberOfTouches = 2;
    

这是访问负责分页 UIPageViewController 的底层滚动视图的方法。将此代码放在例如UIPageViewController(自己)的viewDidLoad:

如果您根本无法访问滚动视图 - 例如动态 UITableViewCell 中的 UIPageViewController,其中创建和单元重用发生在运行时,并且无法在其 contentViews 上设置任何出口 - 将类别放在UIScrollView 并覆盖那里的委托方法。不过要小心!这会影响您的应用程序中的每个滚动视图 - 所以要像上面的“更安全”示例中那样进行适当的自省(类检查)...... ;-)


旁注:

不幸的是,同样的技巧不适用于 pinchGestureRecognizer 上的 UIScrollView,因为它不公开 min/maxNumberOfTouches 属性。当被监控时,它总是报告 2 次触摸(你显然需要捏) - 所以它的内部 min/maxNumberOfTouches 似乎都设置为 2 - 即使 UIScrollView 不遵守自己的设置,并且一直在愉快地用任意数量的手指(超过 2 个)进行捏合。所以没有办法将捏合限制在有限数量的手指上......

【讨论】:

【参考方案2】:

我可以确认这在 iOS 8 中仍然是一个问题,但前提是 UIPanGestureRecognizer 是 UIScrollView 的基础。使用新的 UIPanGestureRecognizer 创建 UIView 并设置其 maximumNumberOfTouches 属性按预期工作。

有趣的提示:如果您在滚动时查询 UIScrollView 的 UIPanGestureRecognizer,它会报告触摸次数小于或等于最大值。换句话说,如果您将最大值设置为 2,并用 3 根手指滚动,它会将手势报告为 2 根手指滚动。随后,在继续滚动的同时一次放开一个手指(但不是始终如一)也会减少报告的触摸次数 - 因此,如果您从 3 -> 2 -> 1 个手指开始,它将记录 2 -> 1 -> 0 次触摸,当您还有 1 根手指在设备上时停止滚动。

提交rdar://20890684并复制到http://openradar.appspot.com/radar?id=6191825677189120。请随意欺骗。

【讨论】:

【参考方案3】:

没有具体的方法可以解决这个问题,只是做一些技巧,但结果只有 75%。

向您的 UIScrollview 添加滑动手势(每个 4 个方向)和双击手势。然后使用下面的代码..

    [[yourScrollView panGestureRecognizer] requireGestureRecognizerToFail:swipeDown];
    [[yourScrollView panGestureRecognizer] requireGestureRecognizerToFail:swipeLeft];
    [[yourScrollView panGestureRecognizer] requireGestureRecognizerToFail:swipeRight];
    [[yourScrollView panGestureRecognizer] requireGestureRecognizerToFail:swipeUp];
    [[yourScrollView panGestureRecognizer] requireGestureRecognizerToFail:doubleTap];

【讨论】:

【参考方案4】:

这将为您完成工作:

yourscrollView.multipleTouchEnabled=NO;

【讨论】:

不会阻止两指或三指滚动。 (在 iOS 12 中测试)。

以上是关于UIScrollView 只能用一根手指滚动的主要内容,如果未能解决你的问题,请参考以下文章

UIScrollView 放大时用 1 根手指平移

如何区分 UIScrollView 中的平移和滚动

试图在 uiscrollview 内部绘制

让 UIScrollView 放弃 UITouch

用两个手指使用 UIScrollView 的自定义容器

如何通过手指获取 UIScrollView 分页?