将UILongPressGestureRecognizer与UIPanGestureRecognizer组合在一起

时间:2010-08-16 10:10:32

标签: objective-c cocoa-touch uigesturerecognizer uipangesturerecognizer uilongpressgesturerecogni

我喜欢将UILongPressGestureRecognizer与UIPanGestureRecognizer结合使用。

UIPanGestureRecognizer应该从长按开始。有一个简单的方法吗?还是我真的要写自己的手势识别器?

我不喜欢在主屏幕上。你按下一个图标,一段时间后图标开始摇晃。之后我没有从屏幕上松开手指,我可以开始拖动手指下的图标。

7 个答案:

答案 0 :(得分:21)

实际上,您不必组合手势识别器 - 您只能使用UILongPressGestureRecognizer执行此操作...一旦您的触摸在'allowableMovement'中保持'minimumPressDuration',您就进入StateBegan。只要你不抬起任何手指,你就会保持连续的longPressGesture - 所以你可以开始移动手指并通过StateChanged跟踪运动。

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

答案 1 :(得分:18)

我遇到这个问题有点困难。接受的答案还不够。无论我在该方法中使用什么,都会调用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设置为NOinit中的viewDidLoad。在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. 然后去喝啤酒祝贺自己。 ;)

答案 2 :(得分:16)

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

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer 
shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer

答案 3 :(得分:7)

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
        }
    } 
    

答案 4 :(得分:0)

阅读Apple的UIGestureRecognizer类参考的“Subclassing Notes”部分:

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

答案 5 :(得分:0)

要组合更多手势:

  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
            }
        }
    

答案 6 :(得分:0)

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

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


// 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)