Пользовательский UIGestureRecognizer не работает, как ожидалось - PullRequest
0 голосов
/ 26 июня 2011

У меня есть UITableView, который я представляю в UIPopoverController.В табличном представлении представлен список элементов, которые можно перетаскивать на основной вид.

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

Мой, к сожалению, долгий путь по этому пути заставил меня создать собственный UIGestureRecognizer.Пытаясь понять основы, я сначала оставил этот пользовательский жест как пустую реализацию, которая просто вызывает супер версию каждого из пяти пользовательских методов, которые, по словам Apple, должны быть переопределены:

(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;
(void)reset;

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

Для моего следующего эксперимента я установил состояние жеста на UIGestureRecognizerStateBegan в методе touchesBegan.

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

Затем я установил состояние жеста на UIGestureRecognizerStateChanged в методе touchesMoved.Все по-прежнему хорошо.

Теперь вместо этого я попытался установить состояние жеста на UIGestureRecognizerStateFailed в методе touchesMoved.Я ожидал, что это завершит жест и восстановит поток событий в табличном представлении, но этого не произошло.Все, что он сделал, это прекратил запуск метода действия жеста.

Наконец, я установил состояние жеста на UIGestureRecognizerStateFailed в методе touchesBegan, сразу после того, как я установил его на UIGestureRecognizerStateBegan.

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

Итак ... извините за такой длинный вопрос ... но почему, если я вызываюжест с ошибкой в ​​методе touchesBegan (после первого задания состояния UIGestureRecognizerStateBegan) перенаправляет события в табличное представление, как и ожидалось.Но если я попробую ту же технику в touchesMoved (единственное место, где я могу обнаружить, что движение в основном вертикальное), почему не происходит такое перенаправление?

Ответы [ 2 ]

1 голос
/ 29 июня 2011

Извините, что сделал это более сложным, чем это было на самом деле. После долгих чтений и испытаний я наконец-то понял, как это сделать.

Во-первых, создание пользовательского UIGestureRecognizer было одним из правильных решений этой проблемы, но когда я сделал свой первый тест пустого пользовательского распознавателя, я сделал ошибку новичка: я забыл вызвать [super touches...:touches withEvent:event] для каждого из методы, которые я преодолел. Из-за этого ничего не происходило, поэтому я установил состояние распознавателя на UIGestureRecognizerStateBegan в touchesBegan, что привело к тому, что метод действия был вызван один раз, таким образом убедив меня, что я должен явно управлять состояниями, что только частично верно.

По правде говоря, если вы создадите пустой пользовательский распознаватель и вызовете соответствующий метод super в каждом перезаписываемом методе, ваша программа будет работать так, как ожидается. В этом случае метод действия будет вызываться во время перемещения. Если в touchesMoved вы установите состояние распознавателя на UIGestureRecognizerStateFailed, события будут пузыриться до суперпредставления (в данном случае UITableView), также как и ожидалось.

Ошибка, которую я допустил, и я думаю, что другие могут сделать, заключается в том, что существует прямая связь между установкой состояния жеста и хронологией стандартных методов, когда вы создаете подкласс распознавателя жестов (т. Е. touchesBegan, touchesMoved и т. Д.). ). Нет - по крайней мере, это не точное отображение. Вам лучше позволить базовому поведению работать как есть, и вмешиваться только в случае необходимости. Итак, в моем случае, как только я определил, что перетаскивание пользователя было преимущественно вертикальным, что я мог сделать только в touchesMoved, я установил состояние распознавателя жестов на UIGestureRecognizerStateFailed в этом методе. Это вывело распознаватель из картинки и автоматически перенаправило полный набор событий в охватывающее представление.

Ради краткости я пропустил массу других вещей, которые я выучил в этом упражнении, но хотел бы отметить, что из шести или семи книг по этому вопросу, IOS 4 по программированию Мэтта Нойбурга обеспечил лучшее объяснение этой темы на сегодняшний день. Я надеюсь, что реферал разрешен на этом сайте. Я никоим образом не связан с автором или издателем - просто благодарен за отличное объяснение!

0 голосов
/ 26 июня 2011

Это, вероятно, происходит потому, что респонденты ожидают увидеть целое прикосновение от начала до конца, а не только его часть.Часто -touchesBegan: ... устанавливает некоторое состояние, которое затем модифицируется в -touchesMoved ..., и для представления действительно не имеет смысла получать -touchesMoved ... без предварительного получения -touchesBegan ...* В документации есть даже примечание, в котором говорится, в частности:

Все просмотренные касания, включая ваше собственное, ожидают (или должны ожидать) получить полное касание.СобытиеЕсли вы запретите объекту-респонденту UIKit получать прикосновения к определенной фазе события, результирующее поведение может быть неопределенным и, вероятно, нежелательным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...