为UISwipeGestureRecognizer设置方向

131

我希望给我的基于视图的iPhone项目添加简单的滑动手势识别,能够识别所有方向(向右、向下、向左、向上)。

在UISwipeGestureRecognizer的文档中说明:

您可以使用按位或运算符指定多个UISwipeGestureRecognizerDirection常量来指定多个方向。默认方向是UISwipeGestureRecognizerDirectionRight。

但是对我来说并没有用。当四个方向都进行OR运算时,只有左右滑动被识别。

- (void)viewDidLoad {
    UISwipeGestureRecognizer *recognizer;

    recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeFrom:)];
    [recognizer setDirection:(UISwipeGestureRecognizerDirectionRight | UISwipeGestureRecognizerDirectionDown | UISwipeGestureRecognizerDirectionLeft | UISwipeGestureRecognizerDirectionUp)];
    [[self view] addGestureRecognizer:recognizer];
    [recognizer release]; 
    [super viewDidLoad];
}

-(void)handleSwipeFrom:(UISwipeGestureRecognizer *)recognizer {
    NSLog(@"Swipe received.");
}

我通过向视图添加四个识别器来解决了这个问题,但我很想知道为什么它没有像文档中所说的那样工作?

- (void)viewDidLoad {
    UISwipeGestureRecognizer *recognizer;

    recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeFrom:)];
    [recognizer setDirection:(UISwipeGestureRecognizerDirectionRight)];
    [[self view] addGestureRecognizer:recognizer];
    [recognizer release];

    recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeFrom:)];
    [recognizer setDirection:(UISwipeGestureRecognizerDirectionUp)];
    [[self view] addGestureRecognizer:recognizer];
    [recognizer release];

    recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeFrom:)];
    [recognizer setDirection:(UISwipeGestureRecognizerDirectionDown)];
    [[self view] addGestureRecognizer:recognizer];
    [recognizer release];

    recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeFrom:)];
    [recognizer setDirection:(UISwipeGestureRecognizerDirectionLeft)];
    [[self view] addGestureRecognizer:recognizer];
    [recognizer release];

    [super viewDidLoad];
}

-(void)handleSwipeFrom:(UISwipeGestureRecognizer *)recognizer {
    NSLog(@"Swipe received.");
}

3
完全没有关联,但是[super viewDidLoad]应该是- (void)viewDidLoad中的第一条语句。 - Mihir Mehta
12个回答

115

似乎存在一个bug。您可以像您之前所做的那样指定允许的方向。但是当您尝试访问触发滑动操作选择器方法中的实际方向时,您仍将获得您最初设置的位掩码(用于允许的方向)。

这意味着当允许超过1个方向时,对于实际方向的检查将始终失败。 您可以通过在选择器方法(即-(void)scrollViewSwiped:(UISwipeGestureRecognizer *)recognizer)中输出'direction'的值,轻松地自行验证。

已向Apple提交了错误报告(#8276386)。

[更新] 我收到了来自Apple的回复,说这种行为是有意而为之。

例如,在表视图中,您可以在表视图单元格中向左或向右滑动以触发“删除”操作(此操作会将滑动手势的方向设置为左和右)。

这意味着原始解决方案就是应该使用的方式。方向属性仅可用于正确识别手势,而不能在成功识别时执行的方法中用于比较实际触发识别的方向。


36
我愿意打赌,几乎每个第一次使用滑动手势识别器的人都会对方向属性的工作方式产生完全相同的错误假设。 - memmons
2
他们的头文件中写道:@property(nonatomic) UISwipeGestureRecognizerDirection direction; // 默认为UISwipeGestureRecognizerDirectionRight。滑动的期望方向。可以指定多个方向。 - nicktmro
1
同意这似乎是苹果方面奇怪的实现。您应该能够指定多个方向,然后测试其中一个方向。 - ChrisP
“方向属性仅用于正确识别手势”是不正确的。我已经使用了 UISwipeGestureRecognizerDirectionUp|UISwipeGestureRecognizerDirectionRight|UISwipeGestureRecognizerDirectionLeft,但它甚至没有触发向上滑动的方法。 - minovsky
@PizzaiolaGorgonzola 他们一定更新了文档,因为目前显示的是0、1、2、3而不是1、2、4、8:https://developer.apple.com/library/ios/DOCUMENTATION/UIKit/Reference/UISwipeGestureRecognizer_Class/Reference/Reference.html#jumpTo_6 - Brandon
显示剩余6条评论

25

我注意到左/右和上/下手势是成对出现的,所以你只需要指定两个手势识别器。而且文档似乎是错误的。


这是正确的解决方案。2个GR,一个用于上下 / 一个用于左右。太棒了! - logancautrell

22

这太糟糕了,我按照Lars提到的方法添加了两个手势,完美解决了问题...

1)左/右 2)上/下

  

UISwipeGestureRecognizer *swipeLeftRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture:)];
    [swipeLeftRight setDirection:(UISwipeGestureRecognizerDirectionRight | UISwipeGestureRecognizerDirectionLeft )];
    [self.view addGestureRecognizer:swipeLeftRight];

    UISwipeGestureRecognizer *swipeUpDown = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture:)];
    [swipeUpDown setDirection:(UISwipeGestureRecognizerDirectionUp | UISwipeGestureRecognizerDirectionDown )];
    [self.view addGestureRecognizer:swipeUpDown];

13
UISwipeGestureRecognizer *recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(didSwipe:)];
[recognizer setDirection:(UISwipeGestureRecognizerDirectionRight)];
[self.view addGestureRecognizer:recognizer];
[recognizer release];

recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(didSwipe:)];
[recognizer setDirection:(UISwipeGestureRecognizerDirectionLeft)];
[self.view addGestureRecognizer:recognizer];
[recognizer release];

现在这是didSwipe函数

- (void) didSwipe:(UISwipeGestureRecognizer *)recognizer{
      if([recognizer direction] == UISwipeGestureRecognizerDirectionLeft){
          //Swipe from right to left
          //Do your functions here
      }else{
          //Swipe from left to right
          //Do your functions here
      }
 }

5
如果要检测所有四个方向,您需要创建四个实例,就像您在解决方法中所做的那样。
原因如下: 您创建的同一 UISwipeGestureRecognizer 实例是传递给选择器作为发送方的实例。因此,如果将其设置为识别所有四个方向,则它将对 sgr.direction == xxx 返回 true,其中 xxx 是任意一个四个方向之一。
以下是另一种解决方法(假定使用 ARC),代码更少:
for(int d = UISwipeGestureRecognizerDirectionRight; d <= UISwipeGestureRecognizerDirectionDown; d = d*2) {
    UISwipeGestureRecognizer *sgr = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeFrom:)];
    sgr.direction = d;
    [self.view addGestureRecognizer:sgr];
}

5
如果您正在使用Xcode 4.2,您可以在故事板中添加手势识别器,然后将GUI手势识别器链接到IBActions。
您可以在实用程序窗格的对象库中找到手势识别器(右窗格底部)。
然后只需控件拖动到适当的操作即可。

3
# Swift 2.1

我必须使用以下内容

    for var x in [
        UISwipeGestureRecognizerDirection.Left,
        UISwipeGestureRecognizerDirection.Right,
        UISwipeGestureRecognizerDirection.Up,
        UISwipeGestureRecognizerDirection.Down
    ] {
        let r = UISwipeGestureRecognizer(target: self, action: "swipe:")
        r.direction = x
        self.view.addGestureRecognizer(r)
    }

2

下面是一段关于UISwipeGestureRecognizer使用的代码示例。注意注释。

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    //add gesture recognizer. The 'direction' property of UISwipeGestureRecognizer only sets the allowable directions. It does not return to the user the direction that was actaully swiped. Must set up separate gesture recognizers to handle the specific directions for which I want an outcome.
    UISwipeGestureRecognizer *gestureRight;
    UISwipeGestureRecognizer *gestureLeft;
    gestureRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeRight:)];//direction is set by default.
    gestureLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeLeft:)];//need to set direction.
    [gestureLeft setDirection:(UISwipeGestureRecognizerDirectionLeft)];
    //[gesture setNumberOfTouchesRequired:1];//default is 1
    [[self view] addGestureRecognizer:gestureRight];//this gets things rolling.
    [[self view] addGestureRecognizer:gestureLeft];//this gets things rolling.
}

swipeRight和swipeLeft是基于左右滑动执行特定活动的方法。例如:

- (void)swipeRight:(UISwipeGestureRecognizer *)gesture
{
    NSLog(@"Right Swipe received.");//Lets you know this method was called by gesture recognizer.
    NSLog(@"Direction is: %i", gesture.direction);//Lets you know the numeric value of the gesture direction for confirmation (1=right).
    //only interested in gesture if gesture state == changed or ended (From Paul Hegarty @ standford U
    if ((gesture.state == UIGestureRecognizerStateChanged) ||
    (gesture.state == UIGestureRecognizerStateEnded)) {

    //do something for a right swipe gesture.
    }
}

2
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");
        //Left
        //Right
        //Top
        //Bottom
    }

1

使用这个,应该是位运算

   gesture.direction & UISwipeGestureRecognizerDirectionUp || 
   gesture.direction & UISwipeGestureRecognizerDirectionDown

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