Распознавать долгое нажатие и распознавание жестов панорамирования вместе

У меня есть вид, к которому я добавил панорамирование и долгое нажатие UIGestureRecognizer. Панорамирование используется для перемещения вида. Что я хотел бы сделать, так это заметить, что касание перестало двигаться (оставаясь активным), и вызвать долгое нажатие.

Что я обнаружил, так это то, что долгое нажатие никогда не срабатывает после начала сковороды. Я попытался установить делегата и реализовать:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    NSLog(@"simultaneous %@", gestureRecognizer.class);
    return YES;
}

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    NSLog(@"require fail %@", gestureRecognizer.class);

    return [gestureRecognizer isKindOfClass:[UIPanGestureRecognizer self]];
    // also tried return YES;
    // also tried return [gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer self]];
}

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

2 ответа

Решение

В случае, если это кому-то еще нужно, вот код, который работает для меня. Цель состоит в том, чтобы иметь представление, чувствительное как к длительному нажатию, так и к панорамированию, включая длинное нажатие, которому не предшествует панорамирование и наоборот.

// setup
@property (strong,nonatomic) NSTimer *timer;          // triggers the long press during pan
@property (strong,nonatomic) UIView *longPressView;   // need this to track long press state

// view is the view we're interested in panning and long pressing
UIPanGestureRecognizer *panGR = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGR:)];
[view addGestureRecognizer:panGR];

// this starts a long press when no pan has occurred
UILongPressGestureRecognizer *longGR = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressGR:)];
[view addGestureRecognizer:longGR];

Когда панорамирование начинается или изменяется, запустите таймер. Если таймер истекает до того, как закончится панорамирование (касание отпускается), то у нас долгое нажатие.

- (void)panGR:(UIPanGestureRecognizer *)gr {
    if (gr.state == UIGestureRecognizerStateBegan) {
        [self startTimer:gr.view];
    } else if (gr.state == UIGestureRecognizerStateChanged) {
        [self startTimer:gr.view];

        // do whatever you want to do with pan state in this method
        // in my case, I'm translating the view here

    } else if (gr.state == UIGestureRecognizerStateEnded) {
        if (self.longPressView) {
            [self longPressEnded];
        } else {
            [self.timer invalidate];
        }
    }
}

Мы даем пользователю информацию о таймере просмотра. Вам может потребоваться сохранить другие части состояния жеста, например, местоположение и т. Д. Сделайте то же самое со словарем информации о пользователе.

- (void)startTimer:(UIView *)view {
    if (self.longPressView) return;
    [self.timer invalidate];
    self.timer = [NSTimer scheduledTimerWithTimeInterval:0.8 target:self
                                                selector:@selector(longPressTimer:)
                                                userInfo:@{ @"view": view} repeats:NO];
}

-(void)longPressTimer:(NSTimer *)timer {

    self.longPressView = timer.userInfo[@"view"];
    [self longPressBegan];
}

Так как метод таймера не будет иметь ассоциированного gr, исключите всю логику, которую мы обычно помещаем в обработчик gr, чтобы он мог вызываться как обработчиком таймера, так и обработчиком gr.

- (void)longPressGR:(UILongPressGestureRecognizer *)gr {

    if (gr.state == UIGestureRecognizerStateBegan) {
        self.longPressView = gr.view;
        [self longPressBegan];
    } else if (gr.state == UIGestureRecognizerStateEnded) {
        [self longPressEnded];
    }
}

- (void)longPressBegan {
    NSLog(@"long press began");
}

- (void)longPressEnded {

    self.longPressView = nil;
    NSLog(@"long press ended");
}

Во-первых, мы должны зарегистрировать события длительного нажатия и жеста страницы, например,

      let longPress = UILongPressGestureRecognizer()
longPress.delegate = self
longPress.addTarget(self, action: #selector(sendMessageLongPress(_:)))

let panGesture = UIPanGestureRecognizer()
panGesture.delegate = self
panGesture.addTarget(self, action: #selector(sendMessagePanGesture(_:)))

self.imgRecord.addGestureRecognizer(longPress)
self.imgRecord.addGestureRecognizer(panGesture)

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

      func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
    return true
}

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

Другие вопросы по тегам