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

Объединение UILongPressGestureRecognizer с UIPanGestureRecognizer

Мне нравится комбинировать UILongPressGestureRecognizer с UIPanGestureRecognizer.

UIPanGestureRecognizer должен начинаться с длительного нажатия. Есть ли простой способ сделать это? или мне действительно нужно написать свой собственный распознаватель жестов?

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

4b9b3361

Ответ 1

Я нашел решение: Этот метод UIGestureRecognizerDelegate делает именно то, что я искал:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer 
shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer

Ответ 2

на самом деле вам не нужно комбинировать распознаватели жестов - вы можете делать это исключительно с помощью UILongPressGestureRecognizer... Вы вводите StateBegan, когда ваши прикосновения остались в пределах допустимого перехода для "minimumPressDuration". Вы остаетесь в своем непрерывном longPressGesture, пока вы не поднимаете ни одного пальца, - поэтому вы можете начать перемещать пальцы и отслеживать движение через StateChanged.

Жесты непрерывной печати непрерывны. Жест начинается (UIGestureRecognizerStateBegan), когда число допустимых пальцев (numberOfTouchesRequired) было нажато в течение заданного периода (minimumPressDuration), и штрихи не выходят за допустимый диапазон движения (допустимое перемещение). Устройство распознавания жестов переходит в состояние изменения всякий раз, когда движется палец, и заканчивается (UIGestureRecognizerStateEnded), когда любой из пальцев поднимается.

Ответ 3

У меня было немного времени для этой проблемы. Принятого ответа было недостаточно. Независимо от того, что я вложил в этот метод, обработчики панорамирования или longpress будут вызваны. Решение, которое я нашел, было следующим:

  • Убедитесь, что делегаты распознавателей жестов назначены одному классу (в моем случае self) и убедитесь, что класс делегата является UIGestureRecognizerDelegate.
  • Добавьте в свой класс следующий метод делегата (в соответствии с приведенным выше ответом):

    - (BOOL) gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer 
    shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { 
         return YES;
    }
    
  • Добавьте в свой класс следующий метод делегата:

    - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
         if([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] && ! shouldAllowPan) {
              return NO;
         }
         return YES;
    }
    
  • Затем добавьте свойство или ivar, который будет отслеживать, нужно ли запустить панорамирование (см. метод выше). В моем случае BOOL shouldAllowPan.

  • Установите BOOL на NO в init или viewDidLoad. Внутри обработчика longPress установите BOOL на YES. Я делаю это так:

    - (void) longPressHandler: (UILongPressGestureRecognizer *) gesture {
    
         if(UIGestureRecognizerStateBegan == gesture.state) {
            shouldAllowPan = NO;
         }
    
         if(UIGestureRecognizerStateChanged == gesture.state) {
            shouldAllowPan = YES;
         }
    }
    
  • Внутри panHandler я проверяю BOOL:

    - (void)panHandler:(UIPanGestureRecognizer *)sender{
        if(shouldAllowPan) {
              // do your stuff
        }
    
  • И, наконец, reset BOOL внутри panHandler:

    else if(sender.state == UIGestureRecognizerStateEnded || sender.state == UIGestureRecognizerStateFailed || sender.state == UIGestureRecognizerStateCancelled) {
        shouldAllowPan = NO;
    }
    
  • И тогда пойди, возьмите пиво, чтобы поздравить себя.;)

Ответ 4

Подход Энди Б. в Свифт,

  • Добавьте делегата UIGestureRecognizerDelegate в класс

    class ViewController: UIViewController, UIGestureRecognizerDelegate
    
  • Добавить переменную-член

    var shouldAllowPan: Bool = false
    
  • Добавьте жесты и добавьте делегат ggter von в VC. Это необходимо, чтобы отключить функции shouldRecognizeSimultaneousWithGestureRecognizer и gestureRecognizerShouldBegin

    // long press
    let longPressRec = UILongPressGestureRecognizer(target: self, action: "longPress:")
    yourView.addGestureRecognizer(longPressRec)
    
    // drag
    let panRec = UIPanGestureRecognizer(target: self, action: "draggedView:")
    panRec.delegate = self
    yourView.addGestureRecognizer(panRec)
    
  • Разрешить одновременные жесты

    func gestureRecognizer(UIGestureRecognizer,
    shouldRecognizeSimultaneouslyWithGestureRecognizer:UIGestureRecognizer) -> Bool {
        // println("shouldRecognizeSimultaneouslyWithGestureRecognizer");
        return true
    }
    
    func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool {
         // We only allow the (drag) gesture to continue if it is within a long press
         if((gestureRecognizer is UIPanGestureRecognizer) && (shouldAllowPan == false)) {
             return false;
         }
         return true;
    }
    
  • Внутри длинного обработчика:

    func longPress(sender: UILongPressGestureRecognizer) {
    
        if(sender.state == .Began) {
            // handle the long press
        }
        else if(sender.state == .Changed){
            shouldAllowPan = true
    
        }
        else if (sender.state == .Ended) {
            shouldAllowPan = false
        }
    }