从UIPanGestureRecognizer获取原始触摸位置

15

我所在的界面上添加了一个UIPanGestureRecognizer手势识别器。
问题是,当触摸被识别为平移手势时,它必须移动几个点,并且我无法在UIGestureRecognizerStateBegan状态下提取原始触摸位置。 在这种状态下,translationInView:值为(0,0),并且任何后续的移动都是从这个点开始计算而不是从原始触摸位置开始计算。

是否有一种方法可以从手势识别器本身提取原始位置,还是我需要重写touchesBegan:方法?


这个链接可能会有所帮助 - http://www.icodeblog.com/2010/10/14/working-with-uigesturerecognizers/ - Caffeinated
现在这很容易,只需要 sender.location(in: self) - Fattie
4个回答

9
您应该能够为手势识别器设置“delegate”并实现。
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch

获得初步接触。


2
这也可以工作。但是,最后我使用了 touchesBegan:。看起来,平移手势识别器确实不知道触摸事件最初从哪里开始。 - antalkerekes

3
您可以通过实现自定义的 PanGestureRecognizer 来解决这个问题,它保存了原始触摸点并使其可供调用者使用。
我选择这种方法是因为我还想控制移动距离以触发 平移手势
对于您的情况来说,这可能有些过度,但它完美地工作,并且比听起来要简单。
要获取触摸点坐标,只需调用:
[sender touchPointInView:yourView] 

替代:

[sender locationInView:yourView]

这是 PanGestureRecognizer.m 的代码:

#import "PanGestureRecognizer.h"
#import <UIKit/UIGestureRecognizerSubclass.h>

@implementation PanGestureRecognizer

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesBegan:touches withEvent:event];
    UITouch *touch = [touches anyObject];

    // touchPoint is defined as: @property (assign,nonatomic) CGPoint touchPoint;

    self.touchPoint = [touch locationInView:nil];   
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesMoved:touches withEvent:event];
    UITouch *touch = [touches anyObject];
    CGPoint p = [touch locationInView:nil];

    // customize the pan distance threshold

    CGFloat dx = fabs(p.x-self.touchPoint.x);
    CGFloat dy = fabs(p.y-self.touchPoint.y);

    if ( dx > 2 || dy > 2)  {
        if (self.state == UIGestureRecognizerStatePossible) {
            [self setState:UIGestureRecognizerStateBegan];
        }
        else {
            [self setState:UIGestureRecognizerStateChanged];
        }
    }
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesEnded:touches withEvent:event];

    if (self.state == UIGestureRecognizerStateChanged) {
        [self setState:UIGestureRecognizerStateEnded];
    }
    else {
        [self setState:UIGestureRecognizerStateCancelled];
    }
}

- (void) reset
{
}

// this returns the original touch point

- (CGPoint) touchPointInView:(UIView *)view
{
    CGPoint p = [view convertPoint:self.touchPoint fromView:nil];

    return p;
}

@end

我不明白应该如何使用这个。 - Iulian Onofrei

0

如果您使用locationInView:而不是translationInView:,您将获得绝对坐标而不是相对坐标。但是,您必须开始平移才能获得输入...为了解决这个问题,您的视图可以是一个UIButton,并且您可以触发一个- (IBAction)buttonWasTouched:(UIButton *)button forEvent:(UIEvent *)event连接到"touch down",如下所示:

-(IBAction)shakeIntensityPanGesturebuttonWasTouched:(UIButton *)button forEvent:(UIEvent *)event
{
    UITouch *touch = [[event allTouches] anyObject];
    CGPoint location = [touch locationInView:touch.view]; //touch location local cordinates
}

-1

您可以使用 UIGestureRecognizerState

- (void) onPanGesture:(UIPanGestureRecognizer *)sender {
    if(sender.state == UIGestureRecognizerStateBegan) {
        origin = [sender locationInView];
    } else {
        current = [sender locationInView];
        // Initial touch stored in origin
    }
}

Swift(类似):

var state = recognizer.state
if state == UIGestureRecognizerState.Began {
    println(recognizer.locationInView(viewForGesture))
    //this will be the point of first touch
}

手势识别器有不同的状态(.Began,.Ended,.Cancelled等)。如果在识别器状态为.Began时获取视图或触摸的位置,则将获得其第一个位置。 - Aiden
将此代码放置在由手势调用的函数内。上面的println行每次触摸/平移只会打印一组坐标对。 - Aiden
2
重写 touchesBegan 并打印其值可以证明它与状态为 .Began 时由 locationInView 返回的值不同。 - par

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