Как заставить UISwipeGestureRecognizer и UIPanGestureRecognizer работать в одном представлении
Как бы вы настроили распознаватели жестов, чтобы вы могли иметь UISwipeGestureRecognizer и UIPanGestureRecognizer работа в то же время? Таким образом, если вы касаетесь и двигаться быстро (быстрый салфетки) он обнаруживает жест как салфетки, но если вы касаетесь затем переместить (короткая задержка между касанием и переместить) он обнаруживает его как кастрюлю?
Я пробовал различные перестановки requireGestureRecognizerToFail и это не помогло именно это сделал так, что если SwipeGesture был слева, то мой жест панорамирования будет работать вверх, вниз и вправо, но любое движение влево было обнаружено жестом салфетки.
4 ответов
вы захотите установить один из двух UIGestureRecognizer
делегаты объекта, который имеет смысл (вероятно self
) тогда слушайте, и вернуть YES
для этого метод:
- (BOOL) gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldRecognizeSimultaneouslyWithGestureRecognizer:
(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}
этот метод вызывается при распознавании жеста либо gestureRecognizer
или otherGestureRecognizer
блокирует другой распознаватель жестов от распознавания его жеста. Обратите внимание, что возврат YES
гарантированно позволяет одновременное распознавание; возврат NO
, С другой стороны, не гарантируется предотвращение одновременного распознавания, поскольку делегат другого распознавателя жестов может возвратить YES
.
использование распознавателя панорамирования для обнаружения прокрутки и панорамирования:
- (void)setupRecognizer
{
UIPanGestureRecognizer* panSwipeRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanSwipe:)];
// Here you can customize for example the minimum and maximum number of fingers required
panSwipeRecognizer.minimumNumberOfTouches = 2;
[targetView addGestureRecognizer:panSwipeRecognizer];
}
#define SWIPE_UP_THRESHOLD -1000.0f
#define SWIPE_DOWN_THRESHOLD 1000.0f
#define SWIPE_LEFT_THRESHOLD -1000.0f
#define SWIPE_RIGHT_THRESHOLD 1000.0f
- (void)handlePanSwipe:(UIPanGestureRecognizer*)recognizer
{
// Get the translation in the view
CGPoint t = [recognizer translationInView:recognizer.view];
[recognizer setTranslation:CGPointZero inView:recognizer.view];
// TODO: Here, you should translate your target view using this translation
someView.center = CGPointMake(someView.center.x + t.x, someView.center.y + t.y);
// But also, detect the swipe gesture
if (recognizer.state == UIGestureRecognizerStateEnded)
{
CGPoint vel = [recognizer velocityInView:recognizer.view];
if (vel.x < SWIPE_LEFT_THRESHOLD)
{
// TODO: Detected a swipe to the left
}
else if (vel.x > SWIPE_RIGHT_THRESHOLD)
{
// TODO: Detected a swipe to the right
}
else if (vel.y < SWIPE_UP_THRESHOLD)
{
// TODO: Detected a swipe up
}
else if (vel.y > SWIPE_DOWN_THRESHOLD)
{
// TODO: Detected a swipe down
}
else
{
// TODO:
// Here, the user lifted the finger/fingers but didn't swipe.
// If you need you can implement a snapping behaviour, where based on the location of your targetView,
// you focus back on the targetView or on some next view.
// It's your call
}
}
}
по умолчанию, когда пользователь пытается провести, жест интерпретируется как панорамирование. Это связано с тем, что жест прокрутки отвечает необходимым условиям, которые должны быть интерпретированы как панорамирование (непрерывный жест), прежде чем он встретит необходимые условия, которые должны быть интерпретированы как свайп (дискретный жест).
необходимо указать связь между двумя распознавателями жестов, вызвав метод requireGestureRecognizerToFail: в распознавателе жестов, который требуется задержка
[self.panRecognizer requireGestureRecognizerToFail:self.swipeRecognizer];
вот полное решение для обнаружения направления панорамирования и салфетки (используя логику swipeThreshold 2cupsOfTech):
public enum PanSwipeDirection: Int {
case up, down, left, right, upSwipe, downSwipe, leftSwipe, rightSwipe
public var isSwipe: Bool { return [.upSwipe, .downSwipe, .leftSwipe, .rightSwipe].contains(self) }
public var isVertical: Bool { return [.up, .down, .upSwipe, .downSwipe].contains(self) }
public var isHorizontal: Bool { return !isVertical }
}
public extension UIPanGestureRecognizer {
public var direction: PanSwipeDirection? {
let SwipeThreshold: CGFloat = 1000
let velocity = self.velocity(in: view)
let isVertical = fabs(velocity.y) > fabs(velocity.x)
switch (isVertical, velocity.x, velocity.y) {
case (true, _, let y) where y < 0: return y < -SwipeThreshold ? .upSwipe : .up
case (true, _, let y) where y > 0: return y > SwipeThreshold ? .downSwipe : .down
case (false, let x, _) where x > 0: return x > SwipeThreshold ? .rightSwipe : .right
case (false, let x, _) where x < 0: return x < -SwipeThreshold ? .leftSwipe : .left
default: return nil
}
}
}
использование:
@IBAction func handlePanOrSwipe(recognizer: UIPanGestureRecognizer) {
if let direction = recognizer.direction {
if direction == .leftSwipe {
//swiped left
} else if direction == .up {
//panned up
} else if direction.isVertical && direction.isSwipe {
//swiped vertically
}
}
}