将 UILongPressGestureRecognizer 与 UIPanGestureRecognizer 相结合

发布于 2024-09-14 11:37:11 字数 223 浏览 5 评论 0原文

我想将 UILongPressGestureRecognizer 与 UIPanGestureRecognizer 结合起来。

UIPanGestureRecognizer 应通过长按启动。有没有一种简单的方法可以做到这一点?或者我真的必须编写自己的手势识别器吗?

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

I d'like to combine a UILongPressGestureRecognizer with a UIPanGestureRecognizer.

The UIPanGestureRecognizer should start with a long press. Is there a simple way to do this? or do I really have to write my own gesture recognizer?

I wan't something like on the home screen. You press on an icon and after some time the icons start wobbling. Afterwards without releasing my finger from the screen I can start dragging the icon under my finger around.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

压抑⊿情绪 2024-09-21 11:37:11

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

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

actually, you don't have to combine gesture recognizers - you can do this solely with UILongPressGestureRecognizer... You enter StateBegan once your touch(es) have stayed within 'allowableMovement' for 'minimumPressDuration'. You stay in your continuous longPressGesture as long as you don't lift any of your fingers - so you can start moving your fingers and track the movement through StateChanged.

Long-press gestures are continuous. The gesture begins (UIGestureRecognizerStateBegan) when the number of allowable fingers (numberOfTouchesRequired) have been pressed for the specified period (minimumPressDuration) and the touches do not move beyond the allowable range of movement (allowableMovement). The gesture recognizer transitions to the Change state whenever a finger moves, and it ends (UIGestureRecognizerStateEnded) when any of the fingers are lifted.

请帮我爱他 2024-09-21 11:37:11

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

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

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

    - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
         if([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer 类]] && !shouldAllowPan) {
              返回否;
         }
         返回是;
    }
    
  4. 然后添加一个属性或 ivar,用于跟踪是否应允许开始平移(请参阅上面的方法)。在我的例子中,BOOL shouldAllowPan

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

    - (void) longPressHandler: (UILongPressGestureRecognizer *) 手势 {
    
         if(UIGestureRecognizerStateBegan ==gesture.state) {
            应该允许潘=否;
         }
    
         if(UIGestureRecognizerStateChanged ==gesture.state) {
            应该允许潘=是;
         }
    }
    
  6. 在 panHandler 内部,我对 BOOL 进行检查:

    - (void)panHandler:(UIPanGestureRecognizer *)sender{
        如果(应该允许潘){
              // 做你的事
        }
    
  7. 最后在 panHandler 中重置 BOOL:

    else if(sender.state == UIGestureRecognizerStateEnded || sender.state == UIGestureRecognizerStateFailed || sender.state == UIGestureRecognizerStateCancelled) {
        应该允许潘=否;
    }
    
  8. 然后去喝杯啤酒祝贺一下自己。 ;)

I had a bit of a hard time for this problem. The accepted answer wasn't enough. No matter what I put in that method the pan or longpress handlers would get invoked. A solution I found was as follows:

  1. Ensure the gesture recognizers' delegates are assigned to the same class (in my case self) and ensure the delegate class is a UIGestureRecognizerDelegate.
  2. Add the following delegate method to your class (as per the answer above):

    - (BOOL) gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer 
    shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { 
         return YES;
    }
    
  3. Add the following delegate method to your class:

    - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
         if([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] && ! shouldAllowPan) {
              return NO;
         }
         return YES;
    }
    
  4. Then add either a property or ivar which will track if the pan should be allowed to begin (see method above). In my case BOOL shouldAllowPan.

  5. Set the BOOL to NO in your init or viewDidLoad. Inside your longPress handler set the BOOL to YES. I do it like this:

    - (void) longPressHandler: (UILongPressGestureRecognizer *) gesture {
    
         if(UIGestureRecognizerStateBegan == gesture.state) {
            shouldAllowPan = NO;
         }
    
         if(UIGestureRecognizerStateChanged == gesture.state) {
            shouldAllowPan = YES;
         }
    }
    
  6. Inside the panHandler I do a check on the BOOL:

    - (void)panHandler:(UIPanGestureRecognizer *)sender{
        if(shouldAllowPan) {
              // do your stuff
        }
    
  7. And finally reset the BOOL within the panHandler:

    else if(sender.state == UIGestureRecognizerStateEnded || sender.state == UIGestureRecognizerStateFailed || sender.state == UIGestureRecognizerStateCancelled) {
        shouldAllowPan = NO;
    }
    
  8. And then go grab a beer to congratulate yourself. ;)

淡忘如思 2024-09-21 11:37:11

我找到了一个解决方案:
这个 UIGestureRecognizerDelegate 方法正是我所寻找的:

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

I found a solution:
This UIGestureRecognizerDelegate method does exactly what I looked for:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer 
shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
提笔书几行 2024-09-21 11:37:11

Andy B 在 Swift 中的方法,

  1. UIGestureRecognizerDelegate 委托添加到类中

    类ViewController:UIViewController、UIGestureRecognizerDelegate
    
  2. 添加成员变量

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

    //长按
    让longPressRec = UILongPressGestureRecognizer(目标:自我,动作:“longPress:”)
    yourView.addGestureRecognizer(longPressRec)
    
    // 拖
    让 panRec = UIPanGestureRecognizer(目标: self, 操作: "draggedView:")
    panRec.delegate = self
    yourView.addGestureRecognizer(panRec)
    
  4. 允许同时手势

    funcgestureRecognizer(UIGestureRecognizer,
    shouldRecognizeSimultaneouslyWithGestureRecognizer:UIGestureRecognizer) ->;布尔{
        // println("shouldRecognizeSimultaneouslyWithGestureRecognizer");
        返回真
    }
    
    funcgestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) ->;布尔{
         // 我们只允许(拖动)手势在长按期间继续
         if((gestureRecognizer 是 UIPanGestureRecognizer) && (shouldAllowPan == false)) {
             返回假;
         }
         返回真;
    }
    
  5. 在长按处理程序内:

    func longPress(发送者: UILongPressGestureRecognizer) {
    
        if(sender.state == .Began) {
            // 处理长按
        }
        else if(sender.state == .Changed){
            应该允许潘 = true
    
        }
        else if (sender.state == .Ended) {
            应该允许潘 = false
        }
    } 
    

Andy B's approach in Swift,

  1. Add the UIGestureRecognizerDelegate delegate to the class

    class ViewController: UIViewController, UIGestureRecognizerDelegate
    
  2. Add a member variable

    var shouldAllowPan: Bool = false
    
  3. Add the gestures and need to add the pan gesture delegate to the VC. This is needed to fire off the shouldRecognizeSimultaneouslyWithGestureRecognizer and gestureRecognizerShouldBegin functions

    // 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. Allow simultaneous gestures

    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. Inside the long press handler:

    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
        }
    } 
    
述情 2024-09-21 11:37:11

要组合更多手势:

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

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

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

    扩展 YourViewController : UIGestureRecognizerDelegate {

    funcgestureRecognizer(_gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) ->布尔{
            返回真
        }
    
    
    
    funcgestureRecognizerShouldBegin(_gestureRecognizer: UIGestureRecognizer) ->;布尔{
             // 我们只允许(拖动)手势在长按期间继续
             if((gestureRecognizer 是 UIPanGestureRecognizer) && (shouldAllowPan == false)) {
                 返回错误
             }
             返回真
        }
    
    
    @objc func startDrag(发送者:UIPanGestureRecognizer) {
    
        if(sender.state == .began) {
                // 处理长按
            }
        else if(sender.state == .changed){
                应该允许潘 = true
    
            }
            else if (sender.state == .ending) {
                应该允许潘 = false
            }
        }
    

For combinate more gesture :

  1. Create a local variable var shouldAllowSecondGesture : Bool = false
  2. Create the two recognizer

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. Extension your VC and implement GestureRecognizerDelegate for implemented this method.

    extension 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
            }
        }
    
夏至、离别 2024-09-21 11:37:11

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

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

Read the "Subclassing Notes" section of Apple's UIGestureRecognizer Class Reference at:

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

长梦不多时 2024-09-21 11:37:11

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

由于“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)


I solved this issue by implementing the desired functionality of the "action: Selector?" func of the UIPanGestureRecognizer within the "action: Selector?" func for the UILongPressGestureRecognizer.

As 'UILongPressGestureRecognizer' has no member 'translation', I calculated the translation by saving the position of the original touch and them extracting it from the actual touch position.


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


~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文