Подтвердить что ты не робот

Как захватить точку, первоначально введенную в UIPanGestureRecognizer?

У меня есть приложение, которое позволяет пользователю трассировать строки на экране. Я делаю это, записывая точки в UIPanGestureRecognizer:

-(void)handlePanFrom:(UIPanGestureRecognizer *)recognizer
{
    CGPoint pixelPos = [recognizer locationInView:rootViewController.glView];
    NSLog(@"recorded point %f,%f",pixelPos.x,pixelPos.y);
}

Это прекрасно работает. Тем не менее, меня очень интересует первый момент, когда пользователь постучал, прежде чем начать панорамирование. Но вышеприведенный код дает мне только то, что произошло после того, как жест был распознан как кастрюля (против крана).

Из документации видно, что может быть нет простого способа определить исходное местоположение в API UIPanGestureRecognizer. Хотя в UIPanGestureRecognizer.h я нашел это объявление:

CGPoint _firstScreenLocation;

... который кажется закрытым, так что не повезло. Я рассматриваю возможность выйти за пределы системы UIGestureRecognizer полностью, чтобы захватить эту начальную точку, и позже ссылаюсь на нее, когда я знаю, что пользователь действительно начал UIPanGesture. Я думал, что попрошу здесь, прежде чем спуститься по этой дороге.

4b9b3361

Ответ 1

Опоздал на вечеринку, но я заметил, что на самом деле ничего выше не отвечает на вопрос, и на самом деле есть способ сделать это. Вы должны создать подкласс UIPanGestureRecognizer и включать:

#import <UIKit/UIGestureRecognizerSubclass.h>

либо в файле Objective-C, в котором вы пишете класс, либо в своем соединительном заголовке Swift. Это позволит вам переопределить метод touchesBegan: 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)
    }
}

Тогда ваше свойство initialTouchLocation будет содержать информацию, которую вы ищете. Конечно, в моем примере я предполагаю, что первое касание в наборе касаний является тем, которое представляет интерес, что имеет смысл, если у вас есть MaximumNumberOfTouches 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)
  }
}

Ответ 2

Вы можете использовать translationInView:, чтобы рассчитать начальное местоположение, если вы не reset между ними. Получите перевод и текущее местоположение касания и используйте его, чтобы найти начальную точку на ощупь.

Ответ 3

@Джон Лоренс прав.

Обновлено для Swift 3:

import UIKit.UIGestureRecognizerSubclass

class PanRecognizerWithInitialTouch : UIPanGestureRecognizer {
  var initialTouchLocation: CGPoint!

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

Обратите внимание, что переменная экземпляра initialTouchLocation не может быть закрытой, если вы хотите получить к ней доступ из вашего экземпляра подкласса (обработчик).

Теперь в обработчике

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

Ответ 4

Вы можете использовать этот метод:

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

Ответ 5

в том же 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);
}

найдите его в описании класса UIGestureRecognizer: https://developer.apple.com/library/ios/documentation/uikit/reference/UIGestureRecognizer_Class/Reference/Reference.html

Ответ 7

Ничего себе, пару лет спустя. Я столкнулся с этой проблемой, но решил ее со статической переменной:

- (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;
    }

}

Переменная устанавливается только тогда, когда состояние распознавателя - UIGestureRecognizerBegan. Поскольку переменная является статической, значение сохраняется для более поздних вызовов методов.

Для моего случая мне просто нужна координата x, но вы можете изменить его на CGPoint, если вам нужно.