【问题标题】:Combine longpress gesture and drag gesture together将长按手势和拖动手势结合在一起
【发布时间】:2012-02-14 05:50:51
【问题描述】:

我正在移动我的观点

UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(moveRight:)];
[panRecognizer setMinimumNumberOfTouches:1];
[panRecognizer setMaximumNumberOfTouches:1];
[panRecognizer setDelegate:self];
[bubbleView[rightCnt] addGestureRecognizer:panRecognizer];
[panRecognizer release];

现在,我想通过长按拖动来做同样的事情。

有什么想法吗?

【问题讨论】:

    标签: iphone objective-c ios uigesturerecognizer


    【解决方案1】:

    UILongPressGestureRecognizer 已经为你做了你想做的事。查看UIGestureRecognizerState 属性。来自documentation

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

    所以基本上在你的UILongPressGestureRecognizerselector 被调用之后你会听 UIGestureRecognizerStateBegan、UIGestureRecognizerStateChanged、UIGestureRecognizerStateEnded。在UIGestureRecognizerStateChanged 期间不断更改您的视图框架。

    - (void)moveRight:(UILongPressGestureRecognizer *)gesture
    {
        if(gesture.state == UIGestureRecognizerStateBegan)
        {
            //if needed do some initial setup or init of views here
        }
        else if(gesture.state == UIGestureRecognizerStateChanged)
        {
            //move your views here.
            [yourView setFrame:];
        }
        else if(gesture.state == UIGestureRecognizerStateEnded)
        {
            //else do cleanup
        }
    }
    

    【讨论】:

    • 我正在使用 CGPoint translatePoint = [(UILongPressGestureRecognizer*)sender translationInView:self.view];但是要长按我必须使用什么?
    • 试试[yourView setFrame:CGRectMake(xCoord,yCoord,height,width)]
    • 但是我怎样才能得到translationPoint
    • 为什么需要translatedPoint?您想长按视图并拖动它吗?在UIGestureRecognizerStateEnded 中,您编写代码来获取该视图的新位置。
    • @SrikarAppal 你没有完全回答这个问题。 PJR 想知道每次调用UIGestureRecognizerStateChanged 时如何获取手指坐标。答案是:使用[myGestureRecognizer locationInView:aView]
    【解决方案2】:
    @implementation MyViewController {
        CGPoint _priorPoint;
    }
    
    - (void)moveRight:(UILongPressGestureRecognizer *)sender {
        UIView *view = sender.view;
        CGPoint point = [sender locationInView:view.superview];
        if (sender.state == UIGestureRecognizerStateChanged) {
            CGPoint center = view.center;
            center.x += point.x - _priorPoint.x;
            center.y += point.y - _priorPoint.y;
            view.center = center;
        }
        _priorPoint = point;
    }
    

    【讨论】:

    • 你最初将priorPoint设置为什么?
    • 你不需要特别设置它,因为sender.stateChanged之前总是Began。这意味着_priorPoint 在使用之前总是会被初始化。
    • 但是priorPoint 最初是从(0.0, 0.0) 开始的,所以使用这个代码,初始触摸会使对象的中心移动超过点位置和中心位置的差值。我必须在Began 状态下将priorPoint 设置为视图的中心
    • 对于未来的读者 - 我希望将 UIPanGestureRecognizer 的拖动运动与使用 UITapGestureRecognizer 对初始点击采取行动的能力相结合。我在这里玩了 UILongPressGestureRecognizer 的答案,但是虽然这似乎对其他人有用,但是在移动对象时计算对象的位置并没有达到使用 UIPanGestureRecognizer 的质量——这就是我最终返回使用的质量。对我来说,this answer 有助于提供一种同时识别手势识别器的解决方案
    【解决方案3】:

    在 Swift 中,这可以使用下面的代码来实现

    class DragView: UIView { 
      // Starting center position
      var initialCenter: CGPoint?
    
      override func didMoveToWindow() {
        super.didMoveToWindow()
        // Add longPress gesture recognizer
        let longPress = UILongPressGestureRecognizer(target: self, action: #selector(longPressAction(gesture:)))
        addGestureRecognizer(longPress)
      }
    
      // Handle longPress action
      func longPressAction(gesture: UILongPressGestureRecognizer) {
        if gesture.state == .began {
            guard let view = gesture.view else {
                return
            }
            initialCenter = gesture.location(in: view.superview)
        }
        else if gesture.state == .changed {
            guard let originalCenter = initialCenter else {
                return
            }
    
            guard let view = gesture.view else {
                return
            }
    
            let point = gesture.location(in: view.superview)
    
            // Calculate new center position
            var newCenter = view.center;
            newCenter.x += point.x - originalCenter.x;
            newCenter.y += point.y - originalCenter.y;
    
            // Update view center
            view.center = newCenter
        }
        else if gesture.state == .ended {
           ...
        }
    }
    

    【讨论】:

      【解决方案4】:

      你不需要声明_priorPoint;

      就我而言,我只希望视图水平移动,所以我只更改 x 坐标。

      这是我的解决方案:

          if (longpressGestRec.state == UIGestureRecognizerStateChanged)
          {
              UIView *view = longpressGestRec.view;
      
              // Location of the touch within the view.
              CGPoint point = [longpressGestRec locationInView:view];
      
              // Calculate new X position based on the amount the gesture
              // has moved plus the size of the view we want to move.
              CGFloat newXLoc = (item.frame.origin.x + point.x) - (item.frame.size.width / 2);
              [item setFrame:CGRectMake(newXLoc,
                                        item.frame.origin.y,
                                        item.frame.size.width,
                                        item.frame.size.height)];
          }
      

      【讨论】:

      • 您的解决方案仅适用于手指后的UIView。想象一下,你从一张图片的一角开始UILongPress,你想向左滑动,这张图片会跳到你手指的位置。就我而言,我必须使用_priorPoint 解决方案。
      【解决方案5】:

      感谢 Hari Kunwar 的 Swift 代码,但 longPressAction 函数没有正确定义。

      这是一个改进的版本:

      @objc func longPressAction(gesture: UILongPressGestureRecognizer)  {
          if gesture.state == UIGestureRecognizerState.began {
          }
          else if gesture.state == .changed {
              guard let view = gesture.view else {
                  return
              }
              let location = gesture.location(in: self.view)
              view.center = CGPoint(x:view.center.x + (location.x - view.center.x),
                                                y:view.center.y + (location.y - view.center.y))
          }
          else if gesture.state == UIGestureRecognizerState.ended{
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-11-23
        • 1970-01-01
        • 2013-07-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多