Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/37.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone 如何捕获最初在UIPangestureRecognitor中点击的点?_Iphone_Objective C_Ios_Uigesturerecognizer_Pan - Fatal编程技术网

Iphone 如何捕获最初在UIPangestureRecognitor中点击的点?

Iphone 如何捕获最初在UIPangestureRecognitor中点击的点?,iphone,objective-c,ios,uigesturerecognizer,pan,Iphone,Objective C,Ios,Uigesturerecognizer,Pan,我有一个应用程序,可以让用户跟踪屏幕上的线条。我是通过在UIPangestureRecognitor中记录点来实现的: -(void)handlePanFrom:(UIPanGestureRecognizer *)recognizer { CGPoint pixelPos = [recognizer locationInView:rootViewController.glView]; NSLog(@"recorded point %f,%f",pixelPos.x,pixelPo

我有一个应用程序,可以让用户跟踪屏幕上的线条。我是通过在UIPangestureRecognitor中记录点来实现的:

-(void)handlePanFrom:(UIPanGestureRecognizer *)recognizer
{
    CGPoint pixelPos = [recognizer locationInView:rootViewController.glView];
    NSLog(@"recorded point %f,%f",pixelPos.x,pixelPos.y);
}
那很好。然而,我对用户在开始平移之前点击的第一点非常感兴趣。但是上面的代码只给出了在手势被识别为平移(而不是轻敲)后发生的点

从文档中可以看出,似乎没有简单的方法来确定UIPangestureRecognitor API中的初始点击位置。尽管在UIPanGestureRecognizer.h中,我发现了以下声明:

CGPoint _firstScreenLocation;

…看起来是私人的,所以运气不好。我正在考虑完全脱离UIGestureRecognizer系统,只是为了捕获最初点击的点,然后在我知道用户确实已经开始UIPanGesture后再参考它。不过,在走这条路之前,我想在这里问一下。

您可以使用UIGestureRecognitzerStateStarted方法。以下是指向UIgestureRecognitor类的Apple文档的链接


您应该能够使用来计算起始位置,除非在两者之间重置它。获取触摸的平移和当前位置,并使用它来查找触摸的起点。

您可以使用以下方法:

CGPoint point    = [gesture locationInView:self.view];

在相同的UIView中放入此方法

//-----------------------------------------------------------------------
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    CGPoint point = [[[event allTouches] anyObject] locationInView:self];
NSLog(@"point.x ,point.y  : %f, %f",point.x ,point.y);
}
请在以下UIgestureRecognitor类参考中查找:

晚会迟到了,但我注意到上面没有任何东西能真正回答这个问题,事实上有一种方法可以做到这一点。您必须将UIPanGestureRecognizer子类化,并包括:

#import <UIKit/UIGestureRecognizerSubclass.h>
#导入
要么在编写类的Objective-C文件中,要么在Swift桥接头中。这将允许您覆盖ToucheSBegind:withEvent方法,如下所示:

class SomeCoolPanGestureRecognizer: UIPanGestureRecognizer {
    private var initialTouchLocation: CGPoint!

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent) {
        super.touchesBegan(touches, withEvent: event)
        initialTouchLocation = touches.first!.locationInView(view)
    }
}
类somecoolPangEstureRecognitor:UIPangEstureRecognitor{
private var initialTouchLocation:CGPoint!
覆盖func touchesBegined(触摸:设置,withEvent事件:UIEvent){
super.touchsbegind(touchs,withEvent:event)
initialTouchLocation=touchs.first!.locationInView(视图)
}
}
然后,您的属性initialTouchLocation将包含您要查找的信息。当然,在我的例子中,我假设触摸集合中的第一次触摸是感兴趣的,如果你的最大触摸次数为1,这是有意义的。你可能想用更复杂的方法来寻找兴趣点

编辑:Swift 5


import UIKit.UIGestureRecognizerSubclass

class InitialPanGestureRecognizer: UIPanGestureRecognizer {
  private var initialTouchLocation: CGPoint!

  override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
    super.touchesBegan(touches, with: event)
    initialTouchLocation = touches.first!.location(in: view)
  }
}

导入UIKit.UIgestureRecognitizerSubclass
类InitialPangEstureRecognitor:UIPangEstureRecognitor{
private var initialTouchLocation:CGPoint!
覆盖func touchesStart(touchs:Set,带有事件:UIEvent){
super.touchesbeated(touches,with:event)
initialTouchLocation=touchs.first!.location(在:视图中)
}
}

哇,晚了几年。。我遇到了这个问题,但用一个静态变量解决了它:

- (IBAction)handleGesture:(UIPanGestureRecognizer *)recog {

    CGPoint loc = [recognizer locationInView:self.container];
    static CGFloat origin = 0.0f;

    switch (recognizer.state) {
        case UIGestureRecognizerStateBegan:
            origin = loc.x;
            break;
        case UIGestureRecognizerStateChanged:
        case UIGestureRecognizerStatePossible:
            // origin is still set here to the original touch point!
            break;
        case UIGestureRecognizerStateEnded:
            break;
        case UIGestureRecognizerStateFailed:
        case UIGestureRecognizerStateCancelled:
            break;
    }

}
该变量仅在识别器状态为UIgestureRecognitizerStart时设置。由于变量是静态的,因此该值将保留到以后的方法调用


在我的例子中,我只需要x坐标,但如果需要,你可以将其更改为CG点。

@John Lawrence做对了

为Swift 3更新:
我还注意到,当我尝试在UIPangestureRecognitor上读取shouldBegin方法中的值时,我只在用户移动一点后(即,当手势开始识别pan时)才看到它的位置。这将是非常有用的,知道这个泛手势实际上是从哪里开始的,这样我就可以决定它是否应该识别

如果不想将UIgestureRecognitor视图作为子类,则有两个选项:

  • ui长按手势识别器,然后将延迟设置为0
  • UIPangestureRecognitor,并在shouldReceiveTouch中捕获起点
  • 如果您有其他手势(如轻触、双击等),则可能需要选项2,因为延迟为0的长按手势识别器将导致其他手势无法正确识别

    如果您不关心其他手势,只希望pan正常工作,那么您可以使用延迟为0的UILongPressGestureRecognitor,因为您不需要手动跟踪起始点,因此更易于维护


    解决方案1:UILongPressGestureRecognitor 优点:简单

    不利于:与其他手势处理者友好相处

    创建手势时,确保设置为
    0
    。这将确保您的所有代理方法(例如,应该开始)都能正确地接受第一次触摸

    由于UILongPressGestureRecognitor是一个(与离散手势识别器相反),因此可以通过处理属性来处理移动,就像处理UIPangEstureRecognitor(也是一个连续手势识别器)一样。从本质上说,你是


    解决方案2:UIPangestureRecognitor 适合:与其他手势识别器配合使用

    不利于:保存启动状态需要花费更多的精力

    步骤如下:

  • 首先,您需要注册为代理并监听shouldReceiveTouch事件

  • 一旦发生这种情况,请将触摸点保存在某个变量中(而不是手势点!)

  • 当需要决定是否真的要开始手势时,请阅读此变量

  • 警告:确保阅读
    触摸位置(in:self)
    而不是
    手势识别器。位置(in:self)
    ,因为前者是准确获取起始位置的唯一方法

    现在,您可以在任何需要的地方使用
    gestureStartPoint
    ,例如应该开始:

    func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
        return isValidStartPoint(gestureStartPoint!)
    }
    

    不幸的是,事实并非如此。在最初的解释中,我应该更具体一些:我实际上在case switch语句中使用uigestureRecognitizerStateStateStart来检测平移手势的开始。
      func handlePan (_ sender: PanRecognizerWithInitialTouch) {
        let pos = sender.location(in: view)
        
        switch (sender.state) {
        case UIGestureRecognizerState.began:
          print("Pan Start at \(sender.initialTouchLocation)")
          
        case UIGestureRecognizerState.changed:
          print("    Move to \(pos)")
    
    let gestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(gestureHandler(_:))
    gestureRecognizer.minimumPressDuration = 0
    
    var gestureStartPoint: CGPoint? = nil
    
    // ...
    
    let gestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(gestureHandler(_:))
    gestureRecognizer.delegate = self
    
    // ...
    
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
        gestureStartPoint = touch.location(in: self)
        return true
    }
    
    func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
        return isValidStartPoint(gestureStartPoint!)
    }