UIGestureRecognizerDelegate для управления жестами, могу ли я отменить касание?

Я работаю над приложением, в котором большинство сенсорных жестов будут жестами панорамирования (но я не использую распознаватель жестов панорамирования). Я использую UIGestureRecognizerDelegate и использую touchesBegan, touchesMoved, touchesEnded и touchesCancelled. Однако на экране есть несколько мест, где, если там начинается панорамирование, я хочу вместо этого распознать это как событие касания. Я могу сделать это, просто распознав местоположение в touchesBegan. Мой вопрос: могу ли я отменить касание в этот момент, чтобы предотвратить продолжение панорамирования? Если панорамирование начинается с этого места на экране, это гарантирует, что пользователь на самом деле не предназначен для панорамирования. Я надеюсь в этом есть смысл.

РЕДАКТИРОВАТЬ: я понял, что дополнительные накладные расходы на управление краном даже для точки, которую следует игнорировать, несущественны, поэтому я думаю, что просто сделаю это. Однако я оставлю вопрос здесь на случай, если есть способ остановить отслеживание жеста.

Мне также нужно предложение о том, как справиться со следующей ситуацией.

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

РЕДАКТИРОВАТЬ: сейчас я проверяю, решит ли этот код эту проблему:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
   return YES;
}

Редактировать: ARC запрещает явное расщепление, поэтому теперь я пересматриваю свой вопрос на более общий вопрос о том, что, если что, я могу сделать, чтобы подавить дальнейшие действия. Или мне просто нужно с этим смириться?


person Victor Engel    schedule 18.12.2012    source источник
comment
Вы можете запретить дальнейшие действия. См. вопрос: stackoverflow.com/questions/11667329/   -  person bibo bode    schedule 18.12.2012
comment
@Fawaz Я не думаю, что это применимо к моей ситуации. У меня есть основной вид, который содержит неизвестное количество подвидов, которые по сути являются движущимися спрайтами. Распознаватель жестов, с которым я работаю, прикреплен к основному представлению, а не к подвидам. Распознаватель никогда не нужно удалять, если я что-то не упустил.   -  person Victor Engel    schedule 18.12.2012


Ответы (4)


Вам нужен метод UIGestureRecognizerDelegate gestureRecognizer:shouldReceiveTouch:. Что касается распознавания, когда начинается второе панорамирование, когда одно уже выполняется, вы можете попробовать переменную состояния, которую вы устанавливаете, когда распознаватель жестов начинает распознавать прикосновения.

person Brendon    schedule 18.12.2012
comment
Я только что провел трассировку местоположений и экземпляров касаний, и я удивлен результатами. По сути, я добавил NSLog, распечатывающий номер экземпляра касания, который я увеличиваю по мере прохождения цикла касаний, и распечатываю местоположение касания. Существует только один экземпляр. Когда я добавляю новое панорамирование, пока выполняется предыдущее, местоположения просто обновляются для каждого, как будто движение переходит от одного к другому. Я думал, что для каждого касания будут отдельные экземпляры касания. - person Victor Engel; 18.12.2012
comment
Забудьте тот предыдущий комментарий. Есть отдельные объекты. Должно быть, где-то у меня ошибка, которая мешает распознать второй. Я поработаю над этой ошибкой, прежде чем вернуться к этому вопросу. - person Victor Engel; 18.12.2012
comment
Вот что, по-видимому, происходит: поток пользовательского интерфейса: 1) пользователь запускает touch1, 2) пользователь перемещает touch1, 3) пользователь запускает touch2, 4) пользователь перемещает touch2, 5) пользователь завершает touch2, 6) пользователь завершает touch1 (вероятно, было все время двигаться). В результате touchesEnded вызывается для touch1, но не для touch2. Это неожиданный результат, и я не знаю, как с этим справиться. Есть сенсорный объект с началом, перемещенным, но без конца или отмененный. Так что моя логика для обработки касания никогда не вызывается. - person Victor Engel; 18.12.2012
comment
Вы пытались установить для распознавателей maximimumNumberOfTouches на 1? Это может устранить вашу проблему со вторым жестом. - person Brendon; 19.12.2012
comment
Что, если я хочу, чтобы было возможно более одного касания? Если бы это было проблемой, я бы ожидал, что один объект с количеством касаний будет отличным от одного. Это не относится к делу. - person Victor Engel; 19.12.2012
comment
Если вам просто нужно два или три касания одновременно, вы можете попробовать использовать столько же распознавателей жестов. Я бы не назвал это отличным решением, но это должно быть легко сделать. - person Brendon; 21.12.2012
comment
В игре, над которой я работаю, может участвовать до четырех игроков, каждый из которых может использовать более одного касания одновременно. Это маловероятно, но вполне возможно, что верхний предел в 11 действительно можно использовать. В любом случае, моя проблема заключалась в том, что в подпредставлении было включено взаимодействие с пользователем. Это в сочетании с отслеживанием касаний по объекту вместо координат решило мою проблему. - person Victor Engel; 22.12.2012

Я не уверен, что полностью понимаю ваш вопрос, но, возможно, это поможет:

Во-первых: с ARC вы не должны пытаться ничего освобождать, но вы можете отключить жест. Например, если вы назвали жест panGesture, вы можете сделать это:

panGesture.enabled = NO;

Вместо того, чтобы пытаться выделить и освободить, просто включите и отключите.

Во-вторых: вы можете отслеживать движения жеста панорамирования. В вашем методе IBAction вы можете зафиксировать координаты первого касания, а затем решить, хотите ли вы, чтобы это движение считалось панорамированием или касанием, в зависимости от того, где начинается жест.

Для получения дополнительной информации о жестах панорамирования я бы посоветовал вам посмотреть здесь:

Учебное пособие по UIGestureRecognizer в iOS 5: сжимание, сведение и многое другое!

и, конечно же, здесь:

Руководство по обработке событий для iOS: распознаватели жестов

person Axeva    schedule 18.12.2012
comment
Я не помню, почему я не использовал распознаватель жестов панорамирования, но у него были слишком строгие ограничения. Думаю, я не указал, что использую UIGestureRecognizerDelegate и фиксирую события начала, перемещения, завершения и отмены. - person Victor Engel; 18.12.2012

нет, вы не можете освободить его, и это все равно не сработает


поскольку вы используете GestureRecognizer, вы можете отменить это

@interface UIGestureRecognizer (Cancel)
- (void)cancel;
@end

@implementation UIGestureRecognizer (Cancel)
- (void)cancel
{
    self.enabled = NO;
    self.enabled = YES;
}
@end

OR

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

сбросьте его на НЕТ в touchesBegan и установите его на ДА, когда вы хотите закончить обработку касаний

OR

вы можете сохранить касания, которые хотите отменить, в NSSET, который вы храните в своем классе, и игнорировать эти касания

person Daij-Djan    schedule 18.12.2012
comment
Вы предполагаете, что существует метод отмены, который я должен использовать (я не вижу его в документации), или что я должен создать свой собственный в своем подклассе? - person Victor Engel; 18.12.2012

Вот решения, которые я использовал.

Чтобы распознать тап, я просто сравниваю координаты сенсорного объекта в точках touchesBegan и touchesEnded и считаю это тапом, если координаты совпадают или сдвинулись незначительно. Я игнорирую touchesMoved, так как касание, начинающееся и заканчивающееся примерно в одном и том же месте, но перемещение между ними, очень маловероятно в моем приложении.

Чтобы распознать второе панорамирование после начала первого панорамирования, я отслеживаю сенсорные объекты. В этом сценарии первое и второе панорамирование получают два разных сенсорных объекта. Первоначально я отслеживал координаты и следовал гирляндной цепочке, сопоставляющей currentLocation с предыдущимLocation, но это не сработало, потому что второе касание по какой-то причине ведет себя иначе, чем первое. В любом случае, отслеживать сенсорные объекты несложно. Что касается кода, то он не «знает», происходит ли второй объект касания одновременно с первым или нет.

person Victor Engel    schedule 22.12.2012