在设置requireGestureToFail后,将UIPanGestureRecognizer和UISwipeGestureRecognizer添加到同一视图会导致冲突

时间:2014-02-12 09:38:23

标签: ios objective-c uigesturerecognizer uipangesturerecognizer

我在同一个视图中添加了一个滑动手势识别器和一个平移手势识别器。这些手势应该是彼此独有的。

为了做到这一点,我在滑动手势上添加了约束

[swipeGesture requireGestureToFail:panGesture];

(因为平移手势应该优先)

问题在于,即使在非常快速的滑动过程中,也始终会调用平移手势。

为了解决这个问题,我将自己设定为pan手势的代表。在委托方法中,我按如下方式设置了一些代码:

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
    // check if it is the relevant view
    if (gestureRecognizer.view == self.myViewWithTwoGestures)
    {
        // check that it is the pan gesture
        if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]])
        {
            UIPanGestureRecognizer *pan = (UIPanGestureRecognizer *)gestureRecognizer;
            CGPoint velocity = [pan velocityInView:gestureRecognizer.view];
            // added an arbitrary velocity for failure
            if (ABS(velocity.y) > 100)
            {
                // fail if the swipe was fast enough - this should allow the swipe gesture to be invoked
                return NO;
            }
        }
    }
    return YES;
}

是否有建议的速度来确保良好的行为?还有另一种方法可以强制平移手势失败吗?

2 个答案:

答案 0 :(得分:10)

根据Apple的文档here(在声明两个手势识别器的特定订单下),让UIPanGestureRecognizerUISwipeGestureRecognizer同时处理同样的观点是要求UISwipeGesureRecognizer在调用UIPanGestureRecognizer之前失败(与你写的相反)。这可能与滑动手势也是平移手势这一事实有关,但相反的情况不一定如此(请参阅此SO问题)。

我写了这段小代码,它设法识别平移和滑动手势:

UIPanGestureRecognizer * pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(panned:)];
UISwipeGestureRecognizer * swipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swiped:)];
[pan requireGestureRecognizerToFail:swipe];
swipe.direction = (UISwipeGestureRecognizerDirectionLeft | UISwipeGestureRecognizerDirectionRight);

-(void)panned:(UIPanGestureRecognizer *)gesture
{
    NSLog(@"Pan");
}

-(void)swiped:(UISwipeGestureRecognizer *)gesture
{
    NSLog(@"Swipe");
}

这并不像你希望的那样好(因为你需要滑动手势失败,在手势开始之前有一点延迟),但它确实有效。 但是,您发布的代码可让您根据自己的喜好微调手势。

答案 1 :(得分:1)

迟到的回应,但是我遇到了类似的问题,我希望在刷卡之前将其平移以进行识别。我能让它工作的唯一方法是使用长按(或类似的东西)来设置标志以将平移手势用作平移或滑动。我最后根本没有使用滑动。即:

- (void) handleLongPress : (UILongPressGestureRecognizer *) gestureRecognizer
{
    if (gestureRecognizer.state == UIGestureRecognizerStateBegan)
    {
        _canSwipe = YES;
    }
    else if (gestureRecognizer.state == UIGestureRecognizerStateEnded)
    {
        _canSwipe = NO;
    }
}

- (void) handleDragging : (id) sender
{
    UIPanGestureRecognizer *pan = (UIPanGestureRecognizer *)sender;
    GLKVector2 dragDelta = GLKVector2Make(0., 0.);

    if (pan.state == UIGestureRecognizerStateBegan || pan.state == UIGestureRecognizerStateChanged)
    {
        _mousePosition = [pan translationInView:self.view];
        if (_beginDragging == NO)
        {
            _beginDragging = YES;
        }
        else
        {
            dragDelta = GLKVector2Make(_mousePosition.x - _prevMousePosition.x, _mousePosition.y - _prevMousePosition.y);
        }

        _prevMousePosition = _mousePosition;
    }
    else
    {
        _beginDragging = NO;
    }

    if (_canSwipe == YES)
    {
        if (dragDelta.x > 0)
        {
            _canSwipe = NO;
            [self.navigationController popToRootViewControllerAnimated:YES];
            NSLog(@"swipe right");
        }
        else if (dragDelta.x < 0)
        {
            _canSwipe = NO;
            [self performSegueWithIdentifier:@"toTableSegue" sender:pan];
            NSLog(@"swipe left");
        }
    }
    else
    {
        _dragDeltaTranslation = GLKVector2Make(dragDelta.x/90, dragDelta.y/90);
        _translationXY = GLKVector2Make(_translationXY.x + _dragDeltaTranslation.x, _translationXY.y - _dragDeltaTranslation.y);
    }
}

基本上是这样的:

  1. 使用长按(或其他一些机制)激活滑动状态(长按很好,因为一旦释放,状态就会转到UIGestureRecognizerStateEnded)
  2. 然后使用摇摄方向确定滑动的方向。 2。