您将如何设置手势识别器,以便您可以同时使用UISwipeGestureRecognizer和UIPanGestureRecognizer?这样,如果您触摸并快速移动(快速滑动),它会将手势检测为滑动,但如果您触摸然后移动(触摸和移动之间的短暂延迟),它会将其检测为平移?
我尝试了requireGestureRecognizerToFail的各种排列,但这并没有完全帮助,它做到了,如果离开 SwipeGesture,那么我的平移手势将向上、向下和向右工作,但滑动手势检测到任何左侧移动。
您将如何设置手势识别器,以便您可以同时使用UISwipeGestureRecognizer和UIPanGestureRecognizer?这样,如果您触摸并快速移动(快速滑动),它会将手势检测为滑动,但如果您触摸然后移动(触摸和移动之间的短暂延迟),它会将其检测为平移?
我尝试了requireGestureRecognizerToFail的各种排列,但这并没有完全帮助,它做到了,如果离开 SwipeGesture,那么我的平移手势将向上、向下和向右工作,但滑动手势检测到任何左侧移动。
您将希望将两个UIGestureRecognizer
委托之一设置为有意义的对象(可能self
),然后收听,并返回YES
此方法:
- (BOOL) gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldRecognizeSimultaneouslyWithGestureRecognizer:
(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}
此方法在识别手势时调用,gestureRecognizer
或者otherGestureRecognizer
会阻止其他手势识别器识别其手势。注意返回YES
保证允许同时识别;NO
另一方面,返回不能保证防止同时识别,因为其他手势识别器的委托可能会返回YES
。
默认情况下,当用户尝试滑动时,手势被解释为平移。这是因为滑动手势在满足被解释为滑动(离散手势)的必要条件之前满足被解释为平移(连续手势)的必要条件。
您需要通过在要延迟的手势识别器上调用 requireGestureRecognizerToFail: 方法来指示两个手势识别器之间的关系
[self.panRecognizer requireGestureRecognizerToFail:self.swipeRecognizer];
- (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
}
}
}
这是检测平移和滑动方向的完整解决方案(利用 2cupsOfTech 的 swipeThreshold 逻辑):
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 {
var direction: PanSwipeDirection? {
let SwipeThreshold: CGFloat = 1000
let velocity = self.velocity(in: view)
let isVertical = abs(velocity.y) > abs(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
}
}
}