如何识别所有四个方向的滑动?

26
我需要识别所有方向的滑动手势(上下左右),虽然不是同时进行,但我需要能够识别它们。
我尝试过:
  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 对象?

8个回答

21

你可以像这样设置方向

  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 ***");
}

测试将会成功(但是它们都会成功,因此你将无法从中获取任何信息)。如果您想区分不同方向的轻扫,则需要单独使用手势识别器。


编辑

如评论中所述,请参阅此答案。显然,即使这样也行不通。建议您只创建有一个方向的轻扫手势以使事情变得更容易。


3
是的。您创建的手势识别器将告诉您发生了一个滑动手势,但不会告诉您是哪个方向。 - jbat100
2
最后一句话:“如果你想区分不同方向的滑动,你需要单独使用手势识别器。” 真的为我节省了时间。 - antonio081014
1
我尝试过这个,但只有在你结合左右或上下时才有效。当你结合这四个方向时,只有左右滑动可以被检测到。 - Danyun Liu
@Danyun 我认为你不应该做任何假设(因为它可能会在操作系统版本之间发生变化,因为它没有记录),我建议你在每个方向上使用一个识别器。 - jbat100
我为其有用性投了赞成票,但看到变量/方法名称使用大驼峰式命名法让我感到难过 :( - Joel Balmer
显示剩余8条评论

4

很遗憾,您不能使用direction属性来监听识别器,它只会给出识别器所检测到的方向。我已经使用了两个不同的UISwipeGestureRecognizer来实现此目的,可以在这里查看我的答案:https://dev59.com/DGoy5IYBdhLWcg3wCpsz#16810160


4

我之前遇到过这个问题。最后我创建了一个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中的数学公式在这里有解释。


2

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

如果您只有一个方向的滑动手势和平移手势,您只需使用以下代码:

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

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

希望在未来,苹果可以让我们向 requireGestureRecognizerToFail: 方法传递一个数组。


目前被接受的答案无法正常工作。这个应该是被接受的答案。 - Rupert Pupkin

1
使用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.
    }
}

使用以下代码更改状态结束代码

//如果您只想从上、下、左、右单向切换

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");
        }

    } 

1
您可以通过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;

0

这可能不是最好的解决方案,但您始终可以为要检测的每个滑动方向指定不同的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");
    }
}

0
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");
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接