您如何设置手势识别器,以便您可以同时使用 UISwipeGestureRecognizer 和 UIPanGestureRecognizer ?这样,如果您快速触摸并快速移动(快速滑动),它会将手势检测为滑动,但如果您触摸然后移动(触摸和移动之间的短暂延迟),它会将其检测为平底锅?
我已经尝试了 requireGestureRecognizerToFail 的各种排列,这并没有完全帮助,它使得如果离开SwipeGesture然后我的平移手势将向上,向下和向右但任何运动通过滑动手势检测到左侧。
答案 0 :(得分:51)
您将要将两个UIGestureRecognizer
的委托中的一个设置为有意义的对象(可能self
)然后侦听,并为此返回YES
{ {3}}:
- (BOOL) gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldRecognizeSimultaneouslyWithGestureRecognizer:
(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}
当gestureRecognizer
或otherGestureRecognizer
识别手势会阻止其他手势识别器识别其手势时,会调用此方法。请注意,保证返回YES
可以同时识别;另一方面,返回NO
并不能保证阻止同时识别,因为其他手势识别器的代表可能会返回YES
。
答案 1 :(得分:5)
Using a pan recognizer to detect swipping and panning:
- (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
}
}
}
答案 2 :(得分:4)
默认情况下,当用户尝试滑动时,手势会被解释为平移。这是因为滑动手势在满足被解释为滑动(离散手势)的必要条件之前满足被解释为平移(连续手势)的必要条件。
您需要通过调用要延迟的手势识别器上的requireGestureRecognizerToFail:方法来指示两个手势识别器之间的关系
[self.panRecognizer requireGestureRecognizerToFail:self.swipeRecognizer];
答案 3 :(得分:0)
以下是检测摇摄和滑动方向的完整解决方案(使用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 {
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
}
}
}