Цель-C: Попытка реализовать собственное перетаскивание в UIScrollView, сталкивающееся с множеством проблем - PullRequest
2 голосов
/ 09 июня 2011

Я пытаюсь переопределить поведение по умолчанию в UITableView (который на самом деле является подклассом UIScrollView).По сути, моя таблица занимает треть экрана, и я хотел бы иметь возможность перетаскивать элементы из таблицы на остальную часть экрана - удерживая и затем перетаскивая, а также перетаскивая перпендикуляр к таблице.Я смог реализовать первый метод с небольшим усилием, используя UIScrollView по умолчанию touchesShouldBegin / touchesShouldCancel и touchesBegan / Moved / Ended-Cancelled, но второй метод доставляет мне серьезные проблемы.

Моя проблема в следующем: я хотел бы иметь возможность обнаруживать перетаскивание, но я также хочу иметь возможность прокручивать, когда не перетаскиваю.Чтобы сделать это, я должен выполнить свое обнаружение перетаскивания до и включая точку, когда вызывается touchchesShouldCancel.(Это потому, что touchesShouldCancel - это точка ветвления, в которой UIScrollView решает, продолжать ли касания к своим подпредставлениям или выполнять прокрутку.) К сожалению, радиус отмены UIScrollView довольно мал, и если пользователь касается ячейки, а затем действительно перемещает палецбыстро, только трогает Начал называется.(Если пользователь движется медленно, мы обычно получаем несколько штрихов перед тем, как вызывается touchesShouldCancel.) В результате у меня нет возможности рассчитать направление касания, поскольку у меня есть только одна точка от touchesBegan.

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

Вместо этого,Я пытался захватить пару вызовов touchesBegan / Moved (максимум 2 или 3) в отдельном представлении наложения поверх UITableView, а затем переадресовал свои касания на стол.Таким образом, моя таблица гарантированно будет знать направление перетаскивания при вызове touchesShouldCancel.Вы можете прочитать о вариациях этого метода здесь:

(Да, они делают вещи немного по-другому,но я думаю, что суть заключается в переадресации касаний в UITableView после предварительной обработки.)

К сожалению, похоже, это не работает.Вызов моего табличного представления с помощью touchesBegan / Moved / Ended-Canceled не перемещает таблицу и не направляет их в представление hitTest таблицы (которое, по моим тестам, является либо самой таблицей, либо ячейкой таблицы).Более того, я проверил, что такое nextResponder для ячеек, и он оказался таблицей, так что это тоже не сработало.Насколько я понимаю, это потому, что UIScrollView в какой-то момент в недалеком прошлом переключился на использование распознавателей жестов для выполнения своего жизненно важного обнаружения перетаскивания / прокрутки, и, насколько мне известно, вы не можете пересылать касания, как обычно, когда распознаватели жестов

Вот еще одна вещь: хотя распознаватели жестов были официально выпущены в 3.2, они все еще существуют в 3.1.3, хотя вы не можете использовать API.Я думаю, что UIScrollView уже использует их в 3.1.3.

Вот так!Итак, вот мои вопросы:

  1. Метод nextResponder, описанный в двух ссылках выше, кажется довольно недавним.Я делаю что-то не так, или с тех пор реализация UIScrollView действительно кардинально изменилась?
  2. Есть ли способ пересылки касаний в класс с помощью UIGestureRecognizer, гарантирующий, что распознаватели имеют возможность обрабатывать касания?
  3. Я могу решить эту проблему, добавив свой собственный UIGestureRecognizer, который определяет угол перетаскивания в моем табличном представлении, и затем убедившись, что каждый распознаватель жестов, добавленный до этого в table.gestureRecognizer, зависит от завершения шахты.(Я думаю, что есть 3 распознавателя жестов UIScrollView по умолчанию. Некоторые из них являются частными классами API, но все они, очевидно, являются подклассами UIGestureRecognizer.)также используя мои знания о внутренностях UIScrollView, которые не задокументированы Apple.Может ли мое приложение быть отклонено из-за этого?
  4. Что мне делать для 3.1.3?UIScrollView, очевидно, уже использует распознаватели жестов, но я не могу получить к ним доступ, потому что API доступен только в 3.2.

Спасибо!

1 Ответ

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

Хорошо, я наконец-то нашел ответ на свою проблему.На самом деле два ответа.

Запутанное решение: подкласс UIWindow и переопределение sendEvent для сохранения местоположения последнего касания.(Переопределение sendEvent является одним из примеров, приведенных в Руководстве по обработке событий.) Затем представление прокрутки может запросить у окна последнее прикосновение при вызове touchchesShouldCancel.

Более простое решение: вскоре после этого я заметил, что FacebookБиблиотека Three20 хранила UITouches, не сохраняя их.Я всегда думал, что вы не должны держать объекты UITouch вне локальной области, но документы Apple только явно запрещают хранение.(«Объект UITouch является постоянным в последовательности мультитач. Вы никогда не должны сохранять объект UITouch при обработке события. Если вам нужно сохранить информацию о касании от одной фазы к другой, вам следует скопировать эту информацию из объекта UITouch. ") Поэтому, возможно, было бы законно просто сохранить исходный UITouch в таблице и запросить его новую позицию при вызове touchesShouldCancel.

К сожалению, в худшем случае оба эти метода дают мне только 2точки выборки, что не очень точное измерение направления.Было бы намного лучше, если бы я мог просто отложить ручную обработку таблицы или вызвать touchShouldCancel вручную, но, насколько я могу судить, это либо очень смешно, либо совершенно невозможно / незаконно сделать это.

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