简体   繁体   English

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

[英]Adding a UIPanGestureRecognizer and a UISwipeGestureRecognizer to same view causes conflicts after setting requireGestureToFail

I added a swipe gesture recognizer and a pan gesture recognizer to the same view. 我在同一个视图中添加了一个滑动手势识别器和一个平移手势识别器。 These gestures should be exclusive to each other. 这些手势应该是彼此独有的。

In order to do this I added the constraint on the swipe gesture 为了做到这一点,我在滑动手势上添加了约束

[swipeGesture requireGestureToFail:panGesture];

(because the pan gesture should get precedence) (因为平移手势应该优先)

Problem is that the pan gesture is always invoked - even during a very fast swipe. 问题是总是调用平移手势 - 即使在非常快速的滑动过程中也是如此。

In order to over come this I set myself as the pan gesture's delegate. 为了克服这个问题,我把自己定位为泛手势的代表。 In the delegate method I set up some code as follows: 在委托方法中,我设置了一些代码,如下所示:

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

Is there a suggested velocity to ensure good behavior? 是否有建议的速度来确保良好的行为? Is there another way to force the pan gesture to fail? 还有另一种方法可以强制平移手势失败吗?

According to Apple's documentation here (under Declaring a Specific Order for Two Gesture Recognizers ) the way to get both UIPanGestureRecognizer and UISwipeGestureRecognizer to work on the same view is by requiring the UISwipeGesureRecognizer to fail before calling the UIPanGestureRecognizer (the opposite of what you wrote). 根据苹果的文档这里 (下声明一个特定的顺序为两个姿势识别器 ),以获得这两种方式UIPanGestureRecognizerUISwipeGestureRecognizer在同一个视图中工作是通过要求UISwipeGesureRecognizer调用之前失败UIPanGestureRecognizer (你写的正好相反)。 This probably has something to do with the fact the a swipe gesture is also a pan gesture but the opposite is not necessarily true (see this SO question). 这可能与滑动手势也是平移手势的事实有关,但相反的情况不一定如此(参见此SO问题)。

I wrote this little piece of code and it manages to recognize both pan and swipe gestures: 我写了这段小代码,它设法识别平移和滑动手势:

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

This doesn't work as well as you'd hope (since you need the swipe gesture to fail there's a small delay before the pan gesture starts) but it does work. 这并不像你希望的那样好(因为你需要滑动手势失败,在平移手势开始之前有一个小延迟),但它确实有效。 The code you posted however gives you the ability to fine tune the gestures to your liking. 但是,您发布的代码可让您根据自己的喜好微调手势。

Late response, but I was having a similar issue where I wanted to pan to be recognized before the swipe. 迟到的回复,但我有一个类似的问题,我想在刷卡之前平移识别。 The only way I could get it working was to use a long press (or something similar) to set a flag to use the pan gesture as a pan or a swipe. 我能让它工作的唯一方法是使用长按(或类似的东西)来设置标志以将平移手势用作平移或滑动。 I ended up not using swipes at all. 我最后根本没有使用滑动。 Ie: 即:

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

So essentially: 基本上:

  1. Use long press (or some other mechanism) to activate a state of swiping (long press is nice because as soon as you release, the state goes to UIGestureRecognizerStateEnded) 使用长按(或其他一些机制)来激活滑动状态(长按很好,因为一旦释放,状态就会转到UIGestureRecognizerStateEnded)
  2. Then use the pan direction to determine the direction of the swipe. 然后使用平移方向确定滑动的方向。 2. 2。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM