20

我想将 UILongPressGestureRecognizer 与 UIPanGestureRecognizer 结合使用。

UIPanGestureRecognizer 应该以长按开始。有没有一种简单的方法可以做到这一点?还是我真的必须编写自己的手势识别器?

我不想在主屏幕上显示类似的东西。您按下一个图标,一段时间后图标开始摆动。之后,无需从屏幕上松开手指,我就可以开始拖动手指下的图标。

4

7 回答 7

24

实际上,您不必组合手势识别器 - 您可以仅使用 UILongPressGestureRecognizer 完成此操作......一旦您的触摸保持在“minimumPressDuration”的“allowableMovement”范围内,您就进入了 StateBegan。只要您不抬起任何手指,您就可以保持连续的 longPressGesture - 因此您可以开始移动手指并通过 StateChanged 跟踪移动。

长按手势是连续的。当允许的手指数量 (numberOfTouchesRequired) 在指定的时间 (minimumPressDuration) 内被按下并且触摸没有超出允许的移动范围 (allowableMovement) 时,手势开始 (UIGestureRecognizerStateBegan)。每当手指移动时,手势识别器就会转换到 Change 状态,并在任何手指抬起时结束 (UIGestureRecognizerStateEnded)。

于 2010-08-26T22:52:07.927 回答
21

这个问题我有点难。接受的答案还不够。无论我在该方法中放入什么,都会调用 pan 或 longpress 处理程序。我找到的解决方案如下:

  1. 确保将手势识别器的委托分配给同一个类(在我的情况下是自己),并确保委托类是UIGestureRecognizerDelegate.
  2. 将以下委托方法添加到您的类(根据上面的答案):

    - (BOOL) gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer 
    shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { 
         return YES;
    }
    
  3. 将以下委托方法添加到您的类:

    - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
         if([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] && ! shouldAllowPan) {
              return NO;
         }
         return YES;
    }
    
  4. 然后添加一个属性或 ivar,它将跟踪是否应该允许开始平移(参见上面的方法)。就我而言BOOL shouldAllowPan

  5. 将 BOOL 设置为NO在您的initorviewDidLoad中。在您的 longPress 处理程序中,将 BOOL 设置为YES. 我这样做:

    - (void) longPressHandler: (UILongPressGestureRecognizer *) gesture {
    
         if(UIGestureRecognizerStateBegan == gesture.state) {
            shouldAllowPan = NO;
         }
    
         if(UIGestureRecognizerStateChanged == gesture.state) {
            shouldAllowPan = YES;
         }
    }
    
  6. 在 panHandler 内部,我检查了 BOOL:

    - (void)panHandler:(UIPanGestureRecognizer *)sender{
        if(shouldAllowPan) {
              // do your stuff
        }
    
  7. 最后在 panHandler 中重置 BOOL:

    else if(sender.state == UIGestureRecognizerStateEnded || sender.state == UIGestureRecognizerStateFailed || sender.state == UIGestureRecognizerStateCancelled) {
        shouldAllowPan = NO;
    }
    
  8. 然后去喝啤酒祝贺自己。;)

于 2013-10-17T16:14:09.837 回答
16

我找到了一个解决方案:这个 UIGestureRecognizerDelegate 方法完全符合我的要求:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer 
shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
于 2010-08-16T12:51:06.420 回答
11

Andy B 在 Swift 中的方法,

  1. UIGestureRecognizerDelegate委托添加到类

    class ViewController: UIViewController, UIGestureRecognizerDelegate
    
  2. 添加成员变量

    var shouldAllowPan: Bool = false
    
  3. 添加手势,需要将平移手势委托添加到VC。这是触发 shouldRecognizeSimultaneouslyWithGestureRecognizer 和 gestureRecognizerShouldBegin 函数所必需的

    // long press
    let longPressRec = UILongPressGestureRecognizer(target: self, action: "longPress:")
    yourView.addGestureRecognizer(longPressRec)
    
    // drag
    let panRec = UIPanGestureRecognizer(target: self, action: "draggedView:")
    panRec.delegate = self
    yourView.addGestureRecognizer(panRec)
    
  4. 允许同时使用手势

    func gestureRecognizer(UIGestureRecognizer,
    shouldRecognizeSimultaneouslyWithGestureRecognizer:UIGestureRecognizer) -> Bool {
        // println("shouldRecognizeSimultaneouslyWithGestureRecognizer");
        return true
    }
    
    func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool {
         // We only allow the (drag) gesture to continue if it is within a long press
         if((gestureRecognizer is UIPanGestureRecognizer) && (shouldAllowPan == false)) {
             return false;
         }
         return true;
    }
    
  5. 在长按处理程序内部:

    func longPress(sender: UILongPressGestureRecognizer) {
    
        if(sender.state == .Began) {
            // handle the long press
        }
        else if(sender.state == .Changed){
            shouldAllowPan = true
    
        }
        else if (sender.state == .Ended) {
            shouldAllowPan = false
        }
    } 
    
于 2015-05-04T14:42:28.673 回答
1

组合更多手势:

  1. 创建局部变量var shouldAllowSecondGesture : Bool = false
  2. 创建两个识别器

let longPressRec = UILongPressGestureRecognizer(target: self, action: #selector(self.startDrag(sender:))) cell.addGestureRecognizer(longPressRec) let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.handlePan(sender:))) cell.isUserInteractionEnabled = true cell.addGestureRecognizer(panGestureRecognizer)

  1. 扩展您的 VC 并实现 GestureRecognizerDelegate 以实现此方法。

    扩展 YourViewController : UIGestureRecognizerDelegate {

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
            return true
        }
    
    
    
    func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
             // We only allow the (drag) gesture to continue if it is within a long press
             if((gestureRecognizer is UIPanGestureRecognizer) && (shouldAllowPan == false)) {
                 return false
             }
             return true
        }
    
    
    @objc func startDrag(sender:UIPanGestureRecognizer) {
    
        if(sender.state == .began) {
                // handle the long press
            }
        else if(sender.state == .changed){
                shouldAllowPan = true
    
            }
            else if (sender.state == .ended) {
                shouldAllowPan = false
            }
        }
    
于 2020-04-04T17:51:38.460 回答
0

阅读 Apple 的 UIGestureRecognizer 类参考的“子类化注释”部分:

https://developer.apple.com/library/prerelease/tvos/documentation/UIKit/Reference/UIGestureRecognizer_Class/

于 2016-01-12T05:38:41.710 回答
0

我通过实现“动作:选择器?”的所需功能解决了这个问题。“动作:选择器?”中 UIPanGestureRecognizer 的函数 UILongPressGestureRecognizer 的函数。

由于“UILongPressGestureRecognizer”没有成员“翻译”,我通过保存原始触摸的位置并将其从实际触摸位置中提取来计算翻译。


// in target class
var initialTouchX : CGFloat
var initialTouchX : CGFloat


// in the @objc func for the UILongPressGestureRecognizer
if sender.state == .began {
   initialTouchX = sender.location(in: sender.view).x
   initialTouchY = sender.location(in: sender.view).y
}

let translation = CGVector(dx: sender.location(in: sender.view).x - initialTouchX, dy: sender.location(in: sender.view).y - initialTouchY)


于 2021-01-12T13:55:46.803 回答