【问题标题】:Adding a UIPanGestureRecognizer and a UISwipeGestureRecognizer to same view causes conflicts after setting requireGestureToFail在设置 requireGestureToFail 后将 UIPanGestureRecognizer 和 UISwipeGestureRecognizer 添加到同一视图会导致冲突
【发布时间】:2014-02-12 09:38:22
【问题描述】:

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

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

[swipeGesture requireGestureToFail:panGesture];

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

问题是平移手势总是被调用 - 即使在非常快速的滑动期间也是如此。

为了克服这个问题,我将自己设置为平移手势的代表。在委托方法中,我设置了一些代码如下:

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

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

【问题讨论】:

  • 你试过- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer方法return YES;吗?
  • 我不想同时使用它——这就是为什么我在问题中写了“独家”

标签: ios objective-c uigesturerecognizer uipangesturerecognizer


【解决方案1】:

根据 Apple 的文档 here(在 Declaring a specific order for two Gesture Recognizers)让 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");
}

这并不像您希望的那样有效(因为您需要滑动手势失败,所以在平移手势开始之前会有一小段延迟)但它确实有效。 但是,您发布的代码使您能够根据自己的喜好微调手势。

【讨论】:

    【解决方案2】:

    响应迟了,但我遇到了类似的问题,我想在滑动之前平移以被识别。我可以让它工作的唯一方法是使用长按(或类似的东西)来设置一个标志以使用平移手势作为平移或滑动。我最终根本没有使用滑动。即:

    - (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.

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-01-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多