我在同一个视图中添加了一个滑动手势识别器和一个平移手势识别器。这些手势应该是彼此独有的。
为了做到这一点,我在滑动手势上添加了约束
[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;
}
是否有建议的速度来确保良好的行为?还有另一种方法可以强制平移手势失败吗?
答案 0 :(得分:10)
根据Apple的文档here(在声明两个手势识别器的特定订单下),让UIPanGestureRecognizer
和UISwipeGestureRecognizer
同时处理同样的观点是要求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);
}
}
基本上是这样的: