【问题标题】:Scrolling with two fingers with a UIScrollView使用 UIScrollView 用两根手指滚动
【发布时间】:2010-10-21 16:39:49
【问题描述】:

我有一个应用程序,我的主视图同时接受touchesBegantouchesMoved,因此接受单指触摸和拖动。我想实现一个UIScrollView,我让它工作,但它覆盖了拖动,因此我的 contentView 永远不会收到它们。我想实现一个UIScrollview,其中两指拖动表示滚动,而单指拖动事件会传递给我的内容视图,因此它可以正常执行。我需要创建自己的UIScrollView 子类吗?

这是我的appDelegate 中的代码,我在其中实现了UIScrollView

@implementation MusicGridAppDelegate

@synthesize window;
@synthesize viewController;
@synthesize scrollView;


- (void)applicationDidFinishLaunching:(UIApplication *)application {    

    // Override point for customization after app launch    
    //[application setStatusBarHidden:YES animated:NO];
    //[window addSubview:viewController.view];

    scrollView.contentSize = CGSizeMake(720, 480);
    scrollView.showsHorizontalScrollIndicator = YES;
    scrollView.showsVerticalScrollIndicator = YES;
    scrollView.delegate = self;
    [scrollView addSubview:viewController.view];
    [window makeKeyAndVisible];
}


- (void)dealloc {
    [viewController release];
    [scrollView release];
    [window release];
    [super dealloc];
}

【问题讨论】:

    标签: iphone objective-c uiscrollview


    【解决方案1】:

    在 SDK 3.2 中,UIScrollView 的触摸处理是使用手势识别器处理的。

    如果要进行两指平移而不是默认的单指平移,可以使用以下代码:

    for (UIGestureRecognizer *gestureRecognizer in scrollView.gestureRecognizers) {     
        if ([gestureRecognizer  isKindOfClass:[UIPanGestureRecognizer class]]) {
            UIPanGestureRecognizer *panGR = (UIPanGestureRecognizer *) gestureRecognizer;
            panGR.minimumNumberOfTouches = 2;               
        }
    }
    

    【讨论】:

    • 我试过这个,但是由于某种原因,滚动视图将任何多点触摸检测为单独的单点触摸(即:两指滑动被检测为两个单指),所以手势永远不会叫。有什么想法吗?
    • 我还设置了这个解决方案:panGR.maximumNumberOfTouches = 2;它似乎设置为一个。到目前为止,这是让双指滚动工作的最简单方法。
    • 这对我很有用。比继承 UIScrollView 来做这个简单的改变要干净得多。
    • 很棒的东西 - 非常快速和简单地解决这个问题。
    • 我尝试了所有这些,我得到的只是:忽略对 [UIPanGestureRecognizer setTranslation:inView:] 的调用,因为手势识别器未激活,启用了多点触控
    【解决方案2】:

    对于 iOS 5+,设置此属性与 Mike Laurence 的回答具有相同的效果:

    self.scrollView.panGestureRecognizer.minimumNumberOfTouches = 2;
    

    panGestureRecognizer 忽略单指拖动,因此将单指拖动事件传递给内容视图。

    【讨论】:

    • 同意,这立即解决了我的问题。谢谢古托!
    • 确实如此。现在谁在使用 iOS 4?
    【解决方案3】:

    在 iOS 3.2+ 中,您现在可以很容易地实现两指滚动。只需将平移手势识别器添加到滚动视图并将其 maximumNumberOfTouches 设置为 1。它将要求所有单指滚动,但允许 2+ 手指滚动将链向上传递到滚动视图的内置平移手势识别器(因此允许正常的滚动行为)。

    UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(recognizePan:)];
    panGestureRecognizer.maximumNumberOfTouches = 1;
    [scrollView addGestureRecognizer:panGestureRecognizer];
    [panGestureRecognizer release];
    

    【讨论】:

    • 效果很好。尽管视图仍在从之前的两指手势滚动,但将一根手指放在屏幕上会继续拖动视图。有没有办法防止这种情况发生?
    • @sharvey,您可以通过消除弹跳来最小化这种情况。我还在寻找其他方法...
    • @Yar 你有没有找到另一种方法来防止这种情况发生?
    • 这似乎是本页所有答案中最适合我的。
    【解决方案4】:

    您需要继承 UIScrollView(当然!)。然后你需要:

    • 制作单指事件以转到您的内容视图(简单),并且

    • 让两指事件滚动滚动视图(可能容易,可能很难,可能不可能)。

    Patrick 的建议通常很好:让您的 UIScrollView 子类了解您的内容视图,然后在触摸事件处理程序中检查手指的数量并相应地转发事件。只需确保 (1) 您发送到内容视图的事件不会通过响应者链返回 UIScrollView(即确保处理所有事件),(2) 尊重通常的触摸事件流(即 touchesBegan,而不是一些 {touchesBegan, touchesMoved, touchesEnded},以 touchesEnded 或 touchesCancelled 结束),尤其是在处理 UIScrollView 时。 #2 可能很棘手。

    如果您决定事件是针对 UIScrollView,另一个技巧是让 UIScrollView 相信您的两指手势实际上是单指手势(因为 UIScrollView 不能用两根手指滚动)。尝试只将一根手指的数据传递给 super(通过过滤 (NSSet *)touches 参数 - 请注意它只包含更改的触摸 - 并完全忽略错误手指的事件)。

    如果这不起作用,你就有麻烦了。从理论上讲,您可以通过创建一个看起来类似于 UITouch 的类来尝试创建人工触摸以提供给 UIScrollView。底层 C 代码不检查类型,因此将 (YourTouch *) 转换为 (UITouch *) 可能会起作用,并且您将能够欺骗 UIScrollView 处理实际上没有发生的触摸。

    您可能想阅读my article on advanced UIScrollView tricks(并在那里查看一些完全不相关的 UIScrollView 示例代码)。

    当然,如果你不能让它工作,总是可以选择手动控制 UIScrollView 的移动,或者使用完全自定义编写的滚动视图。 Three20 library 中有 TTScrollView 类;用户感觉不好,但程序员感觉不错。

    【讨论】:

    • 安德烈,感谢您的解释。实际上,我通过将触摸的一个子集传递给 super... 我创建了一个只有一个触摸事件的 NSSet,并通过了它。但是,我应该在该调用中传递相同的 UIEvent 吗?或者我是否需要在通过之前修改事件中的某些内容?我在向后滚动时遇到了一些意外行为,我认为这是因为我传递给 super 的 UIevent 是原始事件,并且触摸的 NSSet 被修改为只有一次触摸。
    • Craid,我不相信你可以修改 UIEvent,所以如果你的原因是正确的,你就有麻烦了。 :)
    【解决方案5】:

    这个答案一团糟,因为您只能通过阅读所有其他答案和 cmets 找到正确答案(最接近的答案让问题倒退)。接受的答案太模糊而无用,并提出了不同的方法。

    合成,这行得通

        // makes it so that only two finger scrolls go
        for (id gestureRecognizer in self.gestureRecognizers) {     
            if ([gestureRecognizer  isKindOfClass:[UIPanGestureRecognizer class]])
            {
                UIPanGestureRecognizer *panGR = gestureRecognizer;
                panGR.minimumNumberOfTouches = 2;              
                panGR.maximumNumberOfTouches = 2;
            }
        }   
    

    这需要两个手指来滚动。我已经在子类中完成了此操作,但如果没有,只需将 self.gestureRecognizers 替换为 myScrollView.gestureRecognizers 即可。

    我唯一添加的是使用id 来避免丑陋的演员表:)

    这可行,但如果您希望 UIScrollView 也进行缩放,可能会变得非常混乱......手势无法正常工作,因为捏到缩放和滚动可以解决它。如果我找到合适的答案,我会更新这个。

    【讨论】:

    • 这对我不起作用,它只会让 UIScrollView 根本不滚动。
    • @RichardSmith 回到一个最简单的例子并测试它。它绝对适用于两指滚动。
    【解决方案6】:

    我们设法在我们的 iPhone 绘图应用程序中实现了类似的功能,方法是继承 UIScrollView 并以简单粗暴的方式根据触摸次数过滤事件:

    //OCRScroller.h
    @interface OCRUIScrollView: UIScrollView
    {
        double pass2scroller;
    }
    @end
    
    //OCRScroller.mm
    @implementation OCRUIScrollView
    - (id)initWithFrame:(CGRect)aRect {
        pass2scroller = 0;
        UIScrollView* newv = [super initWithFrame:aRect];
        return newv;
    }
    - (void)setupPassOnEvent:(UIEvent *)event {
        int touch_cnt = [[event allTouches] count];
        if(touch_cnt<=1){
            pass2scroller = 0;
        }else{
            double timems = double(CACurrentMediaTime()*1000);
            pass2scroller = timems+200;
        }
    }
    
    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
        [self setupPassOnEvent:event];
        [super touchesBegan:touches withEvent:event];
    }
    - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
        [self setupPassOnEvent:event];
        [super touchesMoved:touches withEvent:event];   
    }
    - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
        pass2scroller = 0;
        [super touchesEnded:touches withEvent:event];
    }
    
    
    - (BOOL)touchesShouldBegin:(NSSet *)touches withEvent:(UIEvent *)event inContentView:(UIView *)view
    {
        return YES;
    }
    
    - (BOOL)touchesShouldCancelInContentView:(UIView *)view
    {
        double timems = double(CACurrentMediaTime()*1000);
        if (pass2scroller == 0 || timems> pass2scroller){
            return NO;
        }
        return YES;
    }
    @end
    

    ScrollView 设置如下:

    scroll_view = [[OCRUIScrollView alloc] initWithFrame:rect];
    scroll_view.contentSize = img_size;
    scroll_view.contentOffset = CGPointMake(0,0);
    scroll_view.canCancelContentTouches = YES;
    scroll_view.delaysContentTouches = NO;
    scroll_view.scrollEnabled = YES;
    scroll_view.bounces = NO;
    scroll_view.bouncesZoom = YES;
    scroll_view.maximumZoomScale = 10.0f;
    scroll_view.minimumZoomScale = 0.1f;
    scroll_view.delegate = self;
    self.view = scroll_view;
    

    简单的点击什么都不做(你可以按照你需要的方式处理它),用两根手指点击可以按预期滚动/缩放视图。没有使用 GestureRecognizer,因此适用于 iOS 3.1

    【讨论】:

      【解决方案7】:

      我对上面的代码做了进一步的改进。问题是,即使我们设置了setCanCancelContentTouches:NO ,我们也遇到了问题,缩放手势会中断内容。它不会取消内容触摸,但同时允许放大。为了防止这种情况,我每次都将 minimumZoomScale 和 maximumZoomScale 设置为相同的值来锁定缩放,计时器会触发。

      一个非常奇怪的行为是,当一个手指事件在允许的时间段内被两个手指手势取消时,计时器将被延迟。它在 touchCanceled 事件被调用后被触发。所以我们遇到了问题,尽管事件已经取消,但我们尝试锁定缩放,因此禁用下一个事件的缩放。 为了处理这种行为,计时器回调方法检查是否之前调用了 touchesCanceled。 @implementation JWTwoFingerScrollView

      #pragma mark -
      #pragma mark Event Passing
      
      
      - (id)initWithCoder:(NSCoder *)coder {
          self = [super initWithCoder:coder];
          if (self) {
              for (UIGestureRecognizer* r in self.gestureRecognizers) {
                  if ([r isKindOfClass:[UIPanGestureRecognizer class]]) {
                      [((UIPanGestureRecognizer*)r) setMaximumNumberOfTouches:2];
                      [((UIPanGestureRecognizer*)r) setMinimumNumberOfTouches:2];
                      zoomScale[0] = -1.0;
                      zoomScale[1] = -1.0;
                  }
                  timerWasDelayed = NO;
              }
          }
          return self;
      }
      -(void)lockZoomScale {    
          zoomScale[0] = self.minimumZoomScale;
          zoomScale[1] = self.maximumZoomScale;
          [self setMinimumZoomScale:self.zoomScale];
          [self setMaximumZoomScale:self.zoomScale];
              NSLog(@"locked %.2f %.2f",self.minimumZoomScale,self.maximumZoomScale);
      }
      -(void)unlockZoomScale {
          if (zoomScale[0] != -1 && zoomScale[1] != -1) {
              [self setMinimumZoomScale:zoomScale[0]];
              [self setMaximumZoomScale:zoomScale[1]];
              zoomScale[0] = -1.0;
              zoomScale[1] = -1.0;
              NSLog(@"unlocked %.2f %.2f",self.minimumZoomScale,self.maximumZoomScale);
          }
      }
      
      - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
          NSLog(@"began %i",[event allTouches].count);
          [self setCanCancelContentTouches:YES];
           if ([event allTouches].count == 1){
               touchesBeganTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(firstTouchTimerFired:) userInfo:nil repeats:NO];
               [touchesBeganTimer retain];
               [touchFilter touchesBegan:touches withEvent:event];
           }
       }
      
      //if one finger touch gets canceled by two finger touch, this timer gets delayed
      // so we can! use this method to disable zooming, because it doesnt get called when two finger touch events are wanted; otherwise we would disable zooming while zooming
      -(void)firstTouchTimerFired:(NSTimer*)timer {
          NSLog(@"fired");
          [self setCanCancelContentTouches:NO];
          //if already locked: unlock
          //this happens because two finger gesture delays timer until touch event finishes.. then we dont want to lock!
          if (timerWasDelayed) {
              [self unlockZoomScale];
          }
          else {
              [self lockZoomScale];
          }
          timerWasDelayed = NO;
       }
      
      - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
      //    NSLog(@"moved %i",[event allTouches].count);
          [touchFilter touchesMoved:touches withEvent:event];
      }
      
       - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
          NSLog(@"ended %i",[event allTouches].count);
          [touchFilter touchesEnded:touches withEvent:event];
          [self unlockZoomScale];
       }
      
       //[self setCanCancelContentTouches:NO];
       -(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
          NSLog(@"canceled %i",[event allTouches].count);
          [touchFilter touchesCancelled:touches withEvent:event];
          [self unlockZoomScale];
           timerWasDelayed = YES;
       }
      
      @end
      

      【讨论】:

        【解决方案8】:

        坏消息:iPhone SDK 3.0 及更高版本,不要再向-touchesBegan: 和 -touchesEnded: **UIScrollview** 子类方法传递任何内容。可以使用touchesShouldBegintouchesShouldCancelInContentView这两种方法,不一样的。

        如果您真的想获得这种接触,请拥有一个 hack 允许这样做。

        UIScrollView 的子类中,像这样覆盖hitTest 方法:

        - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
        
          UIView *result = nil;
          for (UIView *child in self.subviews)
            if ([child pointInside:point withEvent:event])
              if ((result = [child hitTest:point withEvent:event]) != nil)
                break;
        
          return result;
        }
        

        这将传递给你这个触摸的子类,但是你不能取消对UIScrollView 超类的触摸。

        【讨论】:

          【解决方案9】:

          我要做的是让我的视图控制器设置滚动视图:

          [scrollView setCanCancelContentTouches:NO];
          [scrollView setDelaysContentTouches:NO];
          

          在我的子视图中,我有一个计时器,因为两指触摸通常从一根手指开始,然后是两根手指。:

          - (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
              // Hand tool or two or more touches means a pan or zoom gesture.
              if ((selectedTool == kHandToolIndex) || (event.allTouches.count > 1)) {
                  [[self parentScrollView] setCanCancelContentTouches:YES];
                  [firstTouchTimer invalidate];
                  firstTouchTimer = nil;
                  return;
              }
          
              // Use a timer to delay first touch because two-finger touches usually start with one touch followed by a second touch.
              [[self parentScrollView] setCanCancelContentTouches:NO];
              anchorPoint = [[touches anyObject] locationInView:self];
              firstTouchTimer = [NSTimer scheduledTimerWithTimeInterval:kFirstTouchTimeInterval target:self selector:@selector(firstTouchTimerFired:) userInfo:nil repeats:NO];
              firstTouchTimeStamp = event.timestamp;
          }
          

          如果第二个 touchesBegan: 事件出现在多个手指上,则允许滚动视图取消触摸。因此,如果用户使用两根手指进行平移,此视图将收到 touchesCanceled: 消息。

          【讨论】:

            【解决方案10】:

            这似乎是互联网上这个问题的最佳资源。另一个关闭的解决方案can be found here

            我以不同的方式以非常令人满意的方式解决了这个问题,主要是通过将我自己的手势识别器替换为等式。我强烈建议任何试图达到原始发帖人要求的效果的人考虑这种替代方法,而不是 UIScrollView 的激进子类化。

            以下过程将提供:

            • 包含您的自定义视图的UIScrollView

            • 用两根手指缩放和平移(通过UIPinchGestureRecognizer

            • 您的视图对所有其他触摸的事件处理

            首先,假设您有一个视图控制器及其视图。在 IB 中,使视图成为 scrollView 的子视图并调整视图的调整大小规则,使其不会调整大小。在滚动视图的属性中,打开任何显示“反弹”的内容并关闭关闭delaysContentTouches”。此外,您必须将缩放最小值和最大值设置为默认值 1.0 以外的值,因为正如 Apple 的文档所说,这是缩放工作所必需的。

            创建UIScrollView 的自定义子类,并将此滚动视图设为自定义子类。为滚动视图添加一个出口到您的视图控制器并将它们连接起来。你现在已经完全配置好了。

            您需要将以下代码添加到 UIScrollView 子类,以便它透明地传递触摸事件(我怀疑这可以更优雅地完成,甚至可能完全绕过子类):

            #pragma mark -
            #pragma mark Event Passing
            
            - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
                [self.nextResponder touchesBegan:touches withEvent:event];
            }
            - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
                [self.nextResponder touchesMoved:touches withEvent:event];
            }
            - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
                [self.nextResponder touchesEnded:touches withEvent:event];
            }
            - (BOOL)touchesShouldCancelInContentView:(UIView *)view {
                return NO;
            }
            

            将此代码添加到您的视图控制器:

            - (void)setupGestures {
                UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinchGesture:)];
                [self.view addGestureRecognizer:pinchGesture];
                [pinchGesture release];
            }
            
            - (IBAction)handlePinchGesture:(UIPinchGestureRecognizer *)sender {
            if ( sender.state == UIGestureRecognizerStateBegan ) {
                //Hold values
                previousLocation = [sender locationInView:self.view];
                previousOffset = self.scrollView.contentOffset;
                previousScale = self.scrollView.zoomScale;
            } else if ( sender.state == UIGestureRecognizerStateChanged ) {
                //Zoom
                [self.scrollView setZoomScale:previousScale*sender.scale animated:NO];
            
                //Move
                location = [sender locationInView:self.view];
                CGPoint offset = CGPointMake(previousOffset.x+(previousLocation.x-location.x), previousOffset.y+(previousLocation.y-location.y));
                [self.scrollView setContentOffset:offset animated:NO];  
            } else {
                if ( previousScale*sender.scale < 1.15 && previousScale*sender.scale > .85 )
                    [self.scrollView setZoomScale:1.0 animated:YES];
            }
            

            }

            请注意,在此方法中,您必须在视图控制器的类文件中定义许多属性:

            • CGFloat previousScale;
            • CGPoint previousOffset;
            • CGPoint previousLocation;
            • CGPoint location;

            好的,就是这样!

            不幸的是,我无法让 scrollView 在手势期间显示其滚动条。我尝试了所有这些策略:

            //Scroll indicators
            self.scrollView.showsVerticalScrollIndicator = YES;
            self.scrollView.showsVerticalScrollIndicator = YES;
            [self.scrollView flashScrollIndicators];
            [self.scrollView setNeedsDisplay];
            

            我真正喜欢的一件事是,如果您查看最后一行,您会注意到它会抓取大约 100% 的任何最终缩放并将其四舍五入。你可以调整你的容忍度;我在 Pages 的缩放行为中看到了这一点,并认为这会是一个不错的选择。

            【讨论】:

            • 什么是“激进的子类化?”
            【解决方案11】:

            我把它放在 viewDidLoad 方法中,这样就完成了处理两个触摸平移行为的滚动视图和另一个处理单点触摸平移行为的平移手势处理程序 -->

            scrollView.panGestureRecognizer.minimumNumberOfTouches = 2
            
            let panGR = UIPanGestureRecognizer(target: self, action: #selector(ViewController.handlePan(_:)))
            panGR.minimumNumberOfTouches = 1
            panGR.maximumNumberOfTouches = 1
            
            scrollView.gestureRecognizers?.append(panGR)
            

            handlePan 方法是一个附加到 ViewController 的函数,有一个简单的打印语句来验证该方法是否正在输入 -->

            @IBAction func handlePan(_ sender: UIPanGestureRecognizer) {
                print("Entered handlePan numberOfTuoches: \(sender.numberOfTouches)")
            }
            

            HTH

            【讨论】:

              【解决方案12】:

              查看我的solution

              #import “JWTwoFingerScrollView.h”
              
              @implementation JWTwoFingerScrollView
              
              - (id)initWithCoder:(NSCoder *)coder {
                  self = [super initWithCoder:coder];
                  if (self) {
                      for (UIGestureRecognizer* r in self.gestureRecognizers) {
                          NSLog(@“%@”,[r class]);
                          if ([r isKindOfClass:[UIPanGestureRecognizer class]]) {
                              [((UIPanGestureRecognizer*)r) setMaximumNumberOfTouches:2];
                              [((UIPanGestureRecognizer*)r) setMinimumNumberOfTouches:2];
                          }
                      }
                  }
                  return self;
              }
              
              -(void)firstTouchTimerFired:(NSTimer*)timer {
                  [self setCanCancelContentTouches:NO];
              }
              
              - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
                  [self setCanCancelContentTouches:YES];
                  if ([event allTouches].count == 1){
                      touchesBeganTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(firstTouchTimerFired:) userInfo: nil repeats:NO];
                      [touchesBeganTimer retain];
                      [touchFilter touchesBegan:touches withEvent:event];
                  }
              }
              
              - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
                  [touchFilter touchesMoved:touches withEvent:event];
              }
              
              - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
                  NSLog(@“ended %i”,[event allTouches].count);
                  [touchFilter touchesEnded:touches withEvent:event];
              }
              
              -(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
                  NSLog(@“canceled %i”,[event allTouches].count);
                  [touchFilter touchesCancelled:touches withEvent:event];
              }
              
              @end
              

              它不会延迟第一次触摸,并且不会在用户使用一个手指后用两根手指触摸时停止。它仍然允许使用计时器取消刚刚开始的一键式事件。

              【讨论】:

                【解决方案13】:

                是的,您需要继承 UIScrollView 并覆盖其 -touchesBegan:-touchesEnded: 方法以“向上”传递触摸。这可能还涉及具有UIView 成员变量的子类,以便它知道将触摸传递到什么意思。

                【讨论】:

                • 你能澄清一下帕特里克的意思吗?我有 UIScrollView 的子类,但我不知道如何自己实现滚动(移动滚动视图的框架?),我不知道如何将事件传递给我的 UIView(内容)。现在,它的 Responder 方法永远不会被调用。
                • 在创建子类时分配给 UIScrollView 子类中的 UIView 成员变量。然后,实现 -touchesBegan、-touchesMoved 和 -touchesEnded 并让他们简单地将事件“向上”传递(通过调用 [uiViewMemberVariable touchesBegan:...]),除非他们知道这是为他们准备的。
                • 哦,如果你知道它是针对 ScrollView 的,那么只需在其中执行 [super touchesBegan:...]。
                • touchesmoved 和朋友不在 uiscrollview 中工作,因为 3.0。您可能会得到部分手术,但不建议这样做
                【解决方案14】:

                KenshiSwift 4

                中的回答
                for gestureRecognizer: UIGestureRecognizer in self.gestureRecognizers! {
                    if (gestureRecognizer is UIPanGestureRecognizer) {
                        let panGR = gestureRecognizer as? UIPanGestureRecognizer
                        panGR?.minimumNumberOfTouches = 2
                    }
                }
                

                【讨论】:

                  猜你喜欢
                  • 2011-02-01
                  • 2023-03-15
                  • 2020-10-27
                  • 1970-01-01
                  • 2014-04-22
                  • 2017-06-19
                  • 2022-06-16
                  • 2017-01-03
                  • 1970-01-01
                  相关资源
                  最近更新 更多