Как мне зафиксировать точку, первоначально нажатую в UIPanGestureRecognizer? - PullRequest
20 голосов
/ 05 августа 2011

У меня есть приложение, которое позволяет пользователю отслеживать линии на экране. Я делаю это, записывая точки в 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. Я думал, что спрошу здесь, прежде чем идти по этой дороге.

Ответы [ 7 ]

20 голосов
/ 05 июля 2015

Опоздал на вечеринку, но я заметил, что на самом деле ничего на самом деле не отвечает на вопрос, и на самом деле есть способ сделать это. Вы должны создать подкласс 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)
  }
}
19 голосов
/ 05 августа 2011

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

9 голосов
/ 12 мая 2017

@ Джон Лоуренс имеет право.

Обновлено для 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)")
5 голосов
/ 18 июня 2013

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

CGPoint point    = [gesture locationInView:self.view];
1 голос
/ 17 апреля 2014

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

0 голосов
/ 07 декабря 2016

Ух, пару лет спустя .. Я столкнулся с этой проблемой, но решил ее с помощью статической переменной:

- (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, если вам нужно.

0 голосов
/ 05 августа 2011

Вы можете использовать метод UIGestureRecognizerStateBegan. Вот ссылка на документацию Apple по классу UIGestureRecognizer.

http://developer.apple.com/library/ios/ipad/#documentation/uikit/reference/UIGestureRecognizer_Class/Reference/Reference.html%23//apple_ref/occ/cl/UIGestureRecognizer

...