UISwipeGestureRecognizer滑动长度

37
有没有办法获取滑动手势的长度或触摸点,以便我可以计算距离?

我认为你只能从UISwipeGestureRecognizer中获取方向。也许你可以获取触摸开始和结束的位置,并从中计算长度。 - picknick
6个回答

58

无法从滑动手势中获取距离,因为SwipeGesture触发的方法只允许在手势结束时访问位置一次。
也许您想使用UIPanGestureRecognizer。

如果您能够使用平移手势,您可以保存平移的起点,然后在平移结束时计算距离。

- (void)panGesture:(UIPanGestureRecognizer *)sender {
    if (sender.state == UIGestureRecognizerStateBegan) {
        startLocation = [sender locationInView:self.view];
    }
    else if (sender.state == UIGestureRecognizerStateEnded) {
        CGPoint stopLocation = [sender locationInView:self.view];
        CGFloat dx = stopLocation.x - startLocation.x;
        CGFloat dy = stopLocation.y - startLocation.y;
        CGFloat distance = sqrt(dx*dx + dy*dy );
        NSLog(@"Distance: %f", distance);
    }
}

10
如果使用UIPanGestureRecognizer手势识别器,内置方法- (CGPoint)translationInView:(UIView *)view效果非常好。 - Jon
2
你肯定会在这里使用translationInView。也许MB有一天会编辑答案,因为它是如此高端!例如https://dev59.com/0WUo5IYBdhLWcg3woAqu。继续前进... - Fattie
@MatthiasBauch 这是英寸吗? - Apollo

16

在 Swift 中

 override func viewDidLoad() {
    super.viewDidLoad()

    // add your pan recognizer to your desired view
    let panRecognizer = UIPanGestureRecognizer(target: self, action:  #selector(panedView))
    self.view.addGestureRecognizer(panRecognizer)

}

   @objc func panedView(sender:UIPanGestureRecognizer){
        var startLocation = CGPoint()
        //UIGestureRecognizerState has been renamed to UIGestureRecognizer.State in Swift 4
        if (sender.state == UIGestureRecognizer.State.began) {
            startLocation = sender.location(in: self.view)
        }
        else if (sender.state == UIGestureRecognizer.State.ended) {
            let stopLocation = sender.location(in: self.view)
            let dx = stopLocation.x - startLocation.x;
            let dy = stopLocation.y - startLocation.y;
            let distance = sqrt(dx*dx + dy*dy );
            NSLog("Distance: %f", distance);

        if distance > 400 {
            //do what you want to do
        }
    }
}
希望这能帮助所有的Swift先驱们。

2
对于懒惰的人,你应该在你的类中声明 var startLocation = CGPoint() - Radu Ursache
同意@RaduUrsache的观点,以上解决方案中没有存储起始位置的方法。 - Mark Perkins

4
func swipeAction(gesture: UIPanGestureRecognizer) {
    let transition = sqrt(pow(gesture.translation(in: view).x, 2)
                     + pow(gesture.translation(in: view).y, 2))
}

4
请注意:仅提供代码的答案并不受鼓励。请添加一些解释。 - GhostCat
这是计算两点之间距离的公式。https://www.mathsisfun.com/algebra/distance-2-points.html - Hari Kunwar

3
对于我们使用Xamarin的人:
void panGesture(UIPanGestureRecognizer gestureRecognizer) {
    if (gestureRecognizer.State == UIGestureRecognizerState.Began) {
        startLocation = gestureRecognizer.TranslationInView (view)
    } else if (gestureRecognizer.State == UIGestureRecognizerState.Ended) {
        PointF stopLocation = gestureRecognizer.TranslationInView (view);
        float dX = stopLocation.X - startLocation.X;
        float dY = stopLocation.Y - startLocation.Y;
        float distance = Math.Sqrt(dX * dX + dY * dY);
        System.Console.WriteLine("Distance: {0}", distance);
    }
}

2
您只能按照标准方法进行操作:记住touchBegin的触摸点,然后与touchEnd的点进行比较。

0

我有一个类似于Swift答案的实现,可以区分拖动和滑动,计算相对于容器的距离和滑动速度。

@objc private func handleSwipe(sender: UIPanGestureRecognizer) {
    if (sender.state == .began) {
        self.swipeStart.location = sender.location(in: self)
        self.swipeStart.time = Date()
    }
    else if (sender.state == .ended) {
        let swipeStopLocation : CGPoint = sender.location(in: self)
        let dx : CGFloat = swipeStopLocation.x - swipeStart.location.x
        let dy : CGFloat = swipeStopLocation.y - swipeStart.location.y
        let distance : CGFloat = sqrt(dx*dx + dy*dy );
        let speed : CGFloat = distance / CGFloat(Date().timeIntervalSince(self.swipeStart.time))
        let portraitWidth = min(self.frame.size.width, self.frame.size.height)
        print("Distance: \(distance), speed: \(speed), dy: \(dy), dx: \(dx), portraitWidth: \(portraitWidth), c1: \(distance >  portraitWidth * 0.4), c2: \(abs(dy) < abs(dx) * 0.25), c3: \(speed > portraitWidth * 3.0) ")
        if distance >  portraitWidth * 0.4 && abs(dy) < abs(dx) * 0.25 && speed > portraitWidth * 3.0 {
            if dx > 0 {
                delegate?.previousAssetPressed(self)
            }else{
                delegate?.nextAssetPressed(self)
            }
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接