Как отфильтровать сенсорные события для UIScrollView? - PullRequest
2 голосов
/ 03 июня 2010

У меня есть вид, который отображает PDF. Он должен быть масштабируемым, поэтому я также создал UIScrollView, и в его делегате я реализовал viewForZoomingInScrollView, чтобы вернуть представление PDF. Все идет нормально. Однако когда пользователь достигает края увеличенной страницы PDF, я бы хотел перейти на следующую страницу. Звучит легко, но я не могу понять, как это сделать.

Я пробовал несколько разных подходов:

  1. Использование scrollViewDidScroll для определения того, достигла ли прокрутка края. Проблема здесь в том, что если zoomScale равен 1, и поэтому прокрутка невозможна, то эта функция никогда не вызывается. Но UIScrollView по-прежнему поглощает все сенсорные события, поэтому я также не могу определить, достигаю ли края в touchSMoved. Установка canCancelContentTouches на NO, если не масштабировать, не является опцией, так как это также предотвратит увеличение.

  2. Создание подкласса UIScrollView и пересылка некоторых событий касания следующему респонденту. К сожалению, когда UIScrollView обнаруживает операцию перетаскивания и отменяет касание, touchesMoved и touchesEnded больше не вызываются даже для подкласса UIScrollView. Опять же, установка canCancelContentTouches на NO не годится, так как это также помешает некоторым желаемым функциям UIScrollView.

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

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

Похоже, что все, что делает UIScrollView, не инициируется из touchesBegan / touchesMoved, но вместо этого он получает некоторые уведомления о способе касаний до этого. Возможно, каким-то недокументированным способом, который я не могу ни перехватить, ни воспроизвести.

Так есть ли способ получать уведомления обо всех движениях касания, выполненных через UIScrollView, при этом все еще имея возможность использовать (когда применяются определенные условия) UIScrollView для масштабирования и прокрутки?

1 Ответ

0 голосов
/ 04 июня 2010

Хорошо, вот что я сделал в итоге:

  • Оставление всей прокрутки и масштабирования до UIScrollView и обработка перелистывания страниц в scrollViewDidEndDragging UIScrollViewDelegate: willDecelerate: является почти решением, за исключением того, что эта функция никогда не вызывается, если весь контент отображается на экране, поэтому перетаскивание / прокрутка невозможна.
  • В этом случае смахивания обрабатываются в функциях touchesBegan / touchesEnded в ViewController, но для того, чтобы это работало, нам нужно убедиться, что UIScrollView не отменяет эти события. Однако в других случаях UIScrollView должен иметь возможность отменять касания, чтобы он мог выполнять масштабирование и прокрутку.
  • UIScrollView должен иметь возможность отменять касания, если:
    • Прокрутка возможна (и необходима), потому что весь контент не помещается на экране (zoomScale> 1 в моем случае), OR
    • Пользователь коснулся экрана двумя пальцами, чтобы увеличить и уменьшить масштаб.
  • Если прокрутка невозможна, и пользователь нажал на экран одним нажатием, касания не должны отменяться, а события касания должны передаваться в контроллер представления.

  • Итак, я создал подкласс UIScrollView.

  • У этого подкласса есть свойство, указывающее на ViewController.
  • Используя методы touchesXXX, я отслеживаю текущее число касаний.
  • Я пересылаю все сенсорные события в ViewController.
  • И, наконец, я переопределил touchShouldCancelInContentView: и возвращаю NO, когда zoomScale <= 1 и touchCount == 1. </li>
...