【问题标题】:How to recognize swipe in all 4 directions?如何识别所有 4 个方向的滑动?
【发布时间】:2011-11-18 11:35:08
【问题描述】:

我需要识别所有方向的滑动(上/下/左/右)。不是同时,但我需要认出它们。

我试过了:

  UISwipeGestureRecognizer *Swipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(SwipeRecognizer:)];
  Swipe.direction = (UISwipeGestureRecognizerDirectionLeft | 
                     UISwipeGestureRecognizerDirectionRight |
                     UISwipeGestureRecognizerDirectionDown | 
                     UISwipeGestureRecognizerDirectionUp);
  [self.view addGestureRecognizer:Swipe];
  [Swipe release];

SwipeRecognizer 上没有出现任何内容

这是 SwipeRecognizer 的代码:

- (void) SwipeRecognizer:(UISwipeGestureRecognizer *)sender {
  if ( sender.direction == UISwipeGestureRecognizerDirectionLeft )
    NSLog(@" *** SWIPE LEFT ***");
  if ( sender.direction == UISwipeGestureRecognizerDirectionRight )
    NSLog(@" *** SWIPE RIGHT ***");
  if ( sender.direction == UISwipeGestureRecognizerDirectionDown )
    NSLog(@" *** SWIPE DOWN ***");
  if ( sender.direction == UISwipeGestureRecognizerDirectionUp )
    NSLog(@" *** SWIPE UP ***");
}

我该怎么做?如何将所有不同的方向分配给我的 Swipe 对象?

【问题讨论】:

    标签: iphone objective-c ipad uigesturerecognizer uiswipegesturerecognizer


    【解决方案1】:

    你这样设置方向

      UISwipeGestureRecognizer *Swipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(SwipeRecognizer:)];
      Swipe.direction = (UISwipeGestureRecognizerDirectionLeft | 
                         UISwipeGestureRecognizerDirectionRight |
                         UISwipeGestureRecognizerDirectionDown | 
                         UISwipeGestureRecognizerDirectionUp);
    

    这就是你得到回调时的方向,所以你所有的测试都失败是正常的。如果你有

    - (void) SwipeRecognizer:(UISwipeGestureRecognizer *)sender {
      if ( sender.direction | UISwipeGestureRecognizerDirectionLeft )
        NSLog(@" *** SWIPE LEFT ***");
      if ( sender.direction | UISwipeGestureRecognizerDirectionRight )
        NSLog(@" *** SWIPE RIGHT ***");
      if ( sender.direction | UISwipeGestureRecognizerDirectionDown )
        NSLog(@" *** SWIPE DOWN ***");
      if ( sender.direction | UISwipeGestureRecognizerDirectionUp )
        NSLog(@" *** SWIPE UP ***");
    }
    

    测试会成功(但所有测试都会成功,因此您不会从中获得任何信息)。如果您想区分不同方向的滑动,则需要单独的手势识别器。


    编辑

    正如 cmets 中所指出的,请参阅 this answer。显然,即使这样也行不通。您应该创建只有一个方向的滑动,让您的生活更轻松。

    【讨论】:

    • 嗯,比我需要创建 4 个手势,如 UISwipeGestureRecognizer *SwipeLeft; UISwipeGestureRecognizer *SwipeUp; [...]?并分配给[self.view addGestureRecognizer:SwipeLeft]; [self.view addGestureRecognizer:SwipeUp]; [...]这样的视图???
    • 是的。您创建的手势识别器会告诉您在其中一个方向上发生了滑动,但不会告诉您在哪个方向。
    • hello @ibat100 通过使用上面的代码,如果我从左向右或从右向左滑动,一次识别的所有手势。
    • 最后一句,“如果你想区分不同方向的滑动,你需要单独的手势识别器。”真的节省了我的时间。
    • 我试过这个,但它只有在你将左右或上下结合时才有效。结合这四个方向,只能检测到左右滑动。
    【解决方案2】:

    很遗憾,您不能使用direction 属性来监听识别器;它只会为您提供识别器检测到的方向。为此,我使用了两个不同的UISwipeGestureRecognizers,请在此处查看我的答案:https://stackoverflow.com/a/16810160/936957

    【讨论】:

      【解决方案3】:

      我之前确实遇到过这个问题。我最终做的是创建一个 UIView 子类,覆盖 touchesMoved: 并做一些数学计算来计算方向。

      大致思路如下:

      #import "OmnidirectionalControl.h"
      
      typedef NS_ENUM(NSInteger, direction) {
          Down = 0, DownRight = 1,
          Right = 2, UpRight = 3,
          Up = 4, UpLeft = 5,
          Left = 6, DownLeft = 7
      };
      
      @interface OmnidirectionalControl ()
      
      @property (nonatomic) CGPoint startTouch;
      @property (nonatomic) CGPoint endTouch;
      
      @end
      
      -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
          self.startTouch = [[touches allObjects][0] locationInView:self];
      }
      
      -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
          self.lastTouch = [[[touches allObjects] lastObject] locationInView:self];
          NSLog(@"Direction: %d", [self calculateDirectionFromTouches]);
      }
      
      -(direction)calculateDirectionFromTouches {
          NSInteger xDisplacement = self.lastTouch.x-self.startTouch.x;
          NSInteger yDisplacement = self.lastTouch.y-self.startTouch.y;
      
          float angle = atan2(xDisplacement, yDisplacement);
          int octant = (int)(round(8 * angle / (2 * M_PI) + 8)) % 8;
      
          return (direction) octant;
      }
      

      touchesMoved: 中为简单起见,我只记录方向,但您可以使用该信息做您想做的事情(例如,将其传递给代表、发布通知等)。在touchesMoved 中,您还需要一些方法来识别滑动是否完成,但这与问题不太相关,所以我将把它留给您。 calculateDirectionFromTouches 中的数学解释 here

      【讨论】:

        【解决方案4】:

        我终于找到了最简单的答案,如果你同意,请标记为答案。

        如果您只有一个方向滑动 + 平移,您只需说: [myPanRecogznier requireGestureRecognizerToFail:mySwipeRecognizer];

        但是,如果您有两次或多次滑动,则不能将数组传递给该方法。为此,您需要实现 UIGestureRecognizerDelegate。

        例如,如果您想识别 2 次滑动(左右滑动)并且还希望允许用户向上平移,则将手势识别器定义为属性或实例变量,然后将 VC 设置为委托在平移手势识别器上:

        _swipeLeft = [[UISwipeGestureRecognizer alloc] ...]; // use proper init here
        _swipeRight = [[UISwipeGestureRecognizer alloc] ...]; // user proper init here
        _swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
        _swipeRight.direction = UISwipeGestureRecognizerDirectionRight;
        _pan = [[UIPanGestureRecognizer alloc] ...]; // use proper init here
        
        _pan.delegate = self;
        
        // then add recognizers to your view
        

        然后实现 - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer 委托方法,如下所示:

        - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
        {
            if (gestureRecognizer == _pan && (otherGestureRecognizer == _swipeLeft || otherGestureRecognizer == _swipeRight)) {
                return YES;
            }
        
            return NO;
        }
        

        这告诉平移手势识别器仅在左右滑动都无法识别时才起作用 - 完美!

        希望将来 Apple 会让我们将一个数组传递给 requireGestureRecognizerToFail: 方法。

        【讨论】:

        • 当前接受的答案不起作用。这应该是公认的答案。
        【解决方案5】:

        使用 UIPanGestureRecogizer 并检测您关心的滑动方向。有关详细信息,请参阅 UIPanGestureRecognizer 文档。 -rrh

        // add pan recognizer to the view when initialized
        UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panRecognized:)];
        [panRecognizer setDelegate:self];
        [self addGestureRecognizer:panRecognizer]; // add to the view you want to detect swipe on
        
        
        -(void)panRecognized:(UIPanGestureRecognizer *)sender
        {
            if (sender.state == UIGestureRecognizerStateBegan) {
                // you might want to do something at the start of the pan
            }
        
            CGPoint distance = [sender translationInView:self]; // get distance of pan/swipe in the view in which the gesture recognizer was added
            CGPoint velocity = [sender velocityInView:self]; // get velocity of pan/swipe in the view in which the gesture recognizer was added
            float usersSwipeSpeed = abs(velocity.x); // use this if you need to move an object at a speed that matches the users swipe speed
            NSLog(@"swipe speed:%f", usersSwipeSpeed);
            if (sender.state == UIGestureRecognizerStateEnded) {
                [sender cancelsTouchesInView]; // you may or may not need this - check documentation if unsure
                if (distance.x > 0) { // right
                    NSLog(@"user swiped right");
                } else if (distance.x < 0) { //left
                    NSLog(@"user swiped left");
                }
                if (distance.y > 0) { // down
                    NSLog(@"user swiped down");
                } else if (distance.y < 0) { //up
                    NSLog(@"user swiped up");
                }
                // Note: if you don't want both axis directions to be triggered (i.e. up and right) you can add a tolerence instead of checking the distance against 0 you could check for greater and less than 50 or 100, etc.
            }
        }
        

        CHANHE IN STATEEND CODE WIH

        //如果您只想向上、向下、向左和向右滑动一次

        if (sender.state == UIGestureRecognizerStateEnded) {
                [sender cancelsTouchesInView]; // you may or may not need this - check documentation if unsure
                if (distance.x > 0 && abs(distance.x)>abs(distance.y)) { // right
                    NSLog(@"user swiped right");
                } else if (distance.x < 0 && abs(distance.x)>abs(distance.y)) { //left
                    NSLog(@"user swiped left");
                }
                if (distance.y > 0 && abs(distance.y)>abs(distance.x)) { // down
                    NSLog(@"user swiped down");
                } else if (distance.y < 0 && abs(distance.y)>abs(distance.x)) { //up
                    NSLog(@"user swiped up");
                }
        
            } 
        

        【讨论】:

          【解决方案6】:

          你可以通过 SwipeGesture 只添加一条对角线,然后...

              UISwipeGestureRecognizer *swipeV = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(action)];
              UISwipeGestureRecognizer *swipeH = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(action)];
              swipeH.direction = ( UISwipeGestureRecognizerDirectionLeft | UISwipeGestureRecognizerDirectionRight  );
              swipeV.direction = ( UISwipeGestureRecognizerDirectionUp | UISwipeGestureRecognizerDirectionDown );
              [self addGestureRecognizer:swipeH];
              [self addGestureRecognizer:swipeV];
               self.userInteractionEnabled = YES;
          

          【讨论】:

            【解决方案7】:
            UISwipeGestureRecognizer *Updown=[[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(handleGestureNext:)];
                    Updown.delegate=self;
                    [Updown setDirection:UISwipeGestureRecognizerDirectionDown | UISwipeGestureRecognizerDirectionUp];
                    [overLayView addGestureRecognizer:Updown];
            
                    UISwipeGestureRecognizer *LeftRight=[[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(handleGestureNext:)];
                    LeftRight.delegate=self;
                    [LeftRight setDirection:UISwipeGestureRecognizerDirectionLeft | UISwipeGestureRecognizerDirectionRight];
                    [overLayView addGestureRecognizer:LeftRight];
                    overLayView.userInteractionEnabled=NO;
            
            
            -(void)handleGestureNext:(UISwipeGestureRecognizer *)recognizer
            {
                NSLog(@"Swipe Recevied");
            }
            

            【讨论】:

              【解决方案8】:

              这可能不是最佳解决方案,但您始终可以为要检测的每个滑动方向指定不同的 UISwipeGestureRecognizer。

              在 viewDidLoad 方法中只需定义所需的 UISwipeGestureRecognizer:

              - (void)viewDidLoad{
                  UISwipeGestureRecognizer *recognizerUp = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeUp:)];
                  recognizerUp.direction = UISwipeGestureRecognizerDirectionUp;
                  [[self view] addGestureRecognizer:recognizerUp];
              
                  UISwipeGestureRecognizer *recognizerDown = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeDown:)];
                  recognizerDown.direction =  UISwipeGestureRecognizerDirectionDown;
                  [[self view] addGestureRecognizer:recognizerDown];
              }
              

              然后只需实现相应的方法来处理滑动:

              - (void)handleSwipeUp:(UISwipeGestureRecognizer *)sender{
                  if (sender.state == UIGestureRecognizerStateEnded){
                      NSLog(@"SWIPE UP");
                  }
              }
              
              
              - (void)handleSwipeDown:(UISwipeGestureRecognizer *)sender{
                  if (sender.state == UIGestureRecognizerStateEnded){
                      NSLog(@"SWIPE DOWN");
                  }
              }
              

              【讨论】:

                猜你喜欢
                • 2014-08-04
                • 1970-01-01
                • 2012-05-12
                • 1970-01-01
                • 1970-01-01
                • 2021-06-23
                • 1970-01-01
                • 2011-04-08
                • 1970-01-01
                相关资源
                最近更新 更多