В этом уроке мы разберемся с тем как обрабатывать тачи в Android.
MotionEvent - это событие касания экрана. MotionEvent работает с любыми способами ввода:
В рамках этого урока мы будет рассматривать только касания пальцем.
MotionEvent содержит данные только об одном событии, это: касание экрана, нажатие кнопки, перемещение пальца и т.п. Рассмотрим типичный жизненный цикл касаний:

Практически всегда обработка касания начинается с события DOWN, когда пользователь коснулся экрана. Далее, при движении пальца приходит событие MOVE. Завершается жест событием UP - в случае если жест завершен правильно, или событием CANCEL, если жест был отменен. Событий на самом деле больше, но чаще всего придется работать с четырьмя событиями: DOWN, MOVE, UP, CANCEL.
Самая частая ошибка при обработке событий это хранение ссылки на MotionEvent. Никогда не храните ссылки на MotionEvent! Предположим, мы храним предыдущий MotionEvent и сравниваем его с новым. Во время работы приложения мы столкнемся с тем, что у нас все события равны. Почему так получается? Все дело в том, что Android оптимизирует работу с MotionEvent и для того, что бы не создавать и не уничтожать кучу объектов с событиями тачей, события переиспользуются.

Существует MotionEvent Pool который содержит некоторое количество событий ввода. Когда происходит новое событие тача, пул выдает его при помощи метода obtain(). Когда работа с тачем завершена, MotionEvent возвращается обратно в пул при помощи метода recycle().
Как же хранить информацию о тачах?
obtain (главное не забыть вызвать recycle);MotionEvent.Как View понимает что именно ей нужно обработать нажатие? Для этого существует система перехвата тачей:
1) Когда система понимает что произошло событие касания экрана и у нас есть ViewGroup, которое попадает под область касания, она вызывает метод onInterceptTouchEvent.
2) ViewGroup должен ответить будет ли он перехватывать этот тач или нет. В случае, если возвращается true, будет вызван onTouchEvent, в противном случае MotionEvent прокидывается к дочернему View и там вызывается метод onTouchEvent
3) Если View обработал событие, то возвращается true и событие покидает текущую иерархию, в противном случае MotionEvent будет передан обратно родителю и будет вызыван метод onTouchEvent родителя.

Multi touch это события множественного касания. Когда человек использует несколько пальцев одновременно. Для Multi тачей вводятся два новых события
POINTER_DOWN. Прикосновение пальцем;POINTER_UP. Поднятие пальца.Кадому пальцу назначаются два параметра:
индекс. Порядковый номер пальца. Не привязан к пальцу, один палец может иметь разные индексы в течение одного касания.
id. Идентификатор пальца. Привязан к конкретному пальцу от начала и до конца касания
Пример:
Коснулись экран одним пальцем. Его параметры: index = 0, id = 0.

Коснулись экран вторым пальцем. Его параметры: index = 1, id = 1.

Коснулись экран третьим пальцем. Его параметры: index = 2, id = 2.

Уберем крайний левый палец. При таком действии индексы пальцев сдвигаются на один, но id остаются прежними.

Уберем еще один палец слева. Оставшийся палец будет иметь параметры: index = 0, id = 2.

Для того, что бы понять какой жест сейчас производил пользователь приходится обрабатывать очень много данных, хранить все касания, запоминать положение пальцев и т.п. в Android уже есть классы, упрощающие нам работу. Об этих классах пойдет речь в следующих разделах.
Для того, что бы отслеживать скорость перемещения пальцев в Android существует класс VelocityTracker. Работа с ним чем-то похожа на работу с MotionEvent - объекты тоже находятся в пуле и для получения VelocityTracker необходимо вызвать метод obtain:
vt = VelocityTracker.obtain()
Что бы VelocityTracker понимал как пользователь передвигает пальцы, необходимо все MotionEvent передавать в метод addMovement:
vt.addMovement(event)
Когда мы захотим получить текущую скорость перемещения, нужно вызвать метод:
vt.computeCurrentVelocity(VELOCITY_UNITS)
Что такое VELOCITY_UNITS? Это то количество пикселей, относительно которых будет считаться скорость. Например, если VELOCITY_UNITS = 1000, то скорость будет измеряться в том, сколько тысяч пикселей в секунду проходит палец на экране.
После работы, нужно не забывать утилизировать объект вызовом:
vt.recycle()
Класс, который позволяет понять какой именно жест сейчас сделал пользователь. Аналогично с классом VelocityTracker необходимо передавать все тачи в GestureDetector и в случае, если произошел какой-то из известных жестов, будет вызван соответствующий метод:
Но не все жесты распознает GestureDetector, например, для распознавания жеста приближения, есть специальный класс ScaleGestureDetector.
Код примера можно посмотреть тут