ios - 一起识别长按和平移手势识别器

标签 ios uigesturerecognizer

我有一个 View ,我在其中添加了平移和长按 UIGestureRecognizer。平移用于移动 View 。我想要做的是还注意到触摸已停止移动(同时保持事件状态)并触发长按。

我发现在平移开始后,长按永远不会被触发。我试过设置委托(delegate)并实现:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    NSLog(@"simultaneous %@", gestureRecognizer.class);
    return YES;
}

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    NSLog(@"require fail %@", gestureRecognizer.class);

    return [gestureRecognizer isKindOfClass:[UIPanGestureRecognizer self]];
    // also tried return YES;
    // also tried return [gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer self]];
}

我试过欺骗 pan gr 的 allowableMovement,也无济于事。我正要放弃并在 pan gr 中使用一个计时器,它会失效然后在移动时重置,但我希望 SDK 会为我做状态机的事情。

最佳答案

如果其他人需要它,这里是适合我的代码。目标是获得对长按和平移都敏感的 View ,包括之前没有平移的长按,反之亦然。

// setup
@property (strong,nonatomic) NSTimer *timer;          // triggers the long press during pan
@property (strong,nonatomic) UIView *longPressView;   // need this to track long press state

// view is the view we're interested in panning and long pressing
UIPanGestureRecognizer *panGR = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGR:)];
[view addGestureRecognizer:panGR];

// this starts a long press when no pan has occurred
UILongPressGestureRecognizer *longGR = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressGR:)];
[view addGestureRecognizer:longGR];

当平移开始或改变时,启动计时器。如果定时器在平移结束(触摸释放)之前到期,那么我们将长按。

- (void)panGR:(UIPanGestureRecognizer *)gr {
    if (gr.state == UIGestureRecognizerStateBegan) {
        [self startTimer:gr.view];
    } else if (gr.state == UIGestureRecognizerStateChanged) {
        [self startTimer:gr.view];

        // do whatever you want to do with pan state in this method
        // in my case, I'm translating the view here

    } else if (gr.state == UIGestureRecognizerStateEnded) {
        if (self.longPressView) {
            [self longPressEnded];
        } else {
            [self.timer invalidate];
        }
    }
}

我们提供 View 的计时器用户信息。您可能需要存储手势状态的其他部分,例如位置等。使用用户信息字典以相同的方式进行。

- (void)startTimer:(UIView *)view {
    if (self.longPressView) return;
    [self.timer invalidate];
    self.timer = [NSTimer scheduledTimerWithTimeInterval:0.8 target:self
                                                selector:@selector(longPressTimer:)
                                                userInfo:@{ @"view": view} repeats:NO];
}

-(void)longPressTimer:(NSTimer *)timer {

    self.longPressView = timer.userInfo[@"view"];
    [self longPressBegan];
}

由于计时器方法没有关联的 gr,所以我们通常将所有逻辑都放在 gr 处理程序中,以便它可以被计时器处理程序和 gr 处理程序调用。

- (void)longPressGR:(UILongPressGestureRecognizer *)gr {

    if (gr.state == UIGestureRecognizerStateBegan) {
        self.longPressView = gr.view;
        [self longPressBegan];
    } else if (gr.state == UIGestureRecognizerStateEnded) {
        [self longPressEnded];
    }
}

- (void)longPressBegan {
    NSLog(@"long press began");
}

- (void)longPressEnded {

    self.longPressView = nil;
    NSLog(@"long press ended");
}

关于ios - 一起识别长按和平移手势识别器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23026047/

相关文章:

ios - Google Map SDK、iOS 和 -ObjC 问题

swift - 如何检测滑动和拖动之间的手势?

swift - 将滑动手势识别器添加到 uilabel (swift)

ios - UITextView startInteractionWithLinkAtPoint 崩溃仅限 iOS 11

ios - 如何使用 SwiftyJSON 在 Swift 中将字符串转换为 JSON 数组?

ios - 用于发布视频的 Instagram iOS API

ios - WhatsApp 网络客户端如何仍能与最新的 iOS 更新(SDK 版本 13.0+)一起使用?

ios - Swift 子类继承初始值设定项吗?

ios - 在 uiscrollview 中向 uiimageview 添加手势(平移、双击、捏合)

objective-c - 混合 Objective-C 和 Swift : fatal error: use of unimplemented initializer 'init(target:action:)' for class