一起识别长按和平移手势识别器
Posted
技术标签:
【中文标题】一起识别长按和平移手势识别器【英文标题】:Recognize long press and pan gesture recognizers together 【发布时间】:2014-04-12 04:19:55 【问题描述】:我已经添加了平移和长按 UIGestureRecognizer 的视图。平移用于移动视图。我想做的是还注意到触摸已停止移动(同时保持活动状态)并触发长按。
我发现在平底锅开始后长按永远不会触发。我试过设置一个委托并实现:
- (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 会为我完成状态机的工作。
【问题讨论】:
我认为您将不得不使用计时器方法(或类似的方法)。 shouldRequireFailureOfGestureRecognizer: 方法不起作用,因为在您建议的场景中,平移手势识别器永远不应进入失败状态。移动之后,只要手指还在向下,我想pan gr还是会处于UIGestureRecognizerStateChanged的状态。 你是否在视图中添加了长按手势识别器? @mownier,谢谢。是的,我做到了。我不得不自己动手。 【参考方案1】:如果其他人需要它,下面是适合我的代码。目标是获得对长按和平移都敏感的视图,包括前面没有平移的长按,反之亦然。
// 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];
我们提供视图的计时器用户信息。您可能需要存储手势状态的其他部分,例如位置等。使用用户信息字典以相同的方式进行操作。
- (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];
由于 timer 方法没有关联的 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");
【讨论】:
这是否允许在长按之前检测到平移手势?因此,如果检测到长按,用户不会将手指从屏幕上移开然后尝试平移手势吗?【参考方案2】:首先我们必须注册长按和翻页手势事件,例如,
let longPress = UILongPressGestureRecognizer()
longPress.delegate = self
longPress.addTarget(self, action: #selector(sendMessageLongPress(_:)))
let panGesture = UIPanGestureRecognizer()
panGesture.delegate = self
panGesture.addTarget(self, action: #selector(sendMessagePanGesture(_:)))
self.imgRecord.addGestureRecognizer(longPress)
self.imgRecord.addGestureRecognizer(panGesture)
然后我们必须设置通过委托方法捕获多个触摸事件。为此,我们必须扩展 UIGestureRecognizerDelegate 然后使用,
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool
return true
然后我们可以根据需要实现事件。 (在我的情况下,如果用户滑动,我想取消录制音频,那么我必须根据需要考虑触摸开始点和触摸结束点。)
【讨论】:
以上是关于一起识别长按和平移手势识别器的主要内容,如果未能解决你的问题,请参考以下文章