What is motion event in android
Объект класса MotionEvent используется для сообщения о событиях перемещения (мыши, пера, пальца, трекбола). Motion events (события перемещения) могут содержать либо абсолютные, либо относительные перемещения и другие данные, в зависимости от типа устройства.
[Обзор класса MotionEvent]
События перемещения описывают перемещения в виде кода действий (action code) и набора значений осей координат. Action code указывает изменение состояния, которое происходит, когда указатель опускается или поднимается. Значения координат осей описывают позицию и другие свойства перемещения.
Например, когда пользователь первый раз касается экрана, система передает событие касания (touch event) к соответствующему элементу визуального интерфейса View с кодом действия ACTION_DOWN (это и есть action code), с набором координат X и Y точки касания, и с информацией о давлении, размере и ориентации области касания.
Некоторые устройства могут сообщать о сразу нескольких путях перемещения, происходящих одновременно. Экраны с поддержкой мультитача (Multi-touch screens, экраны с определением множественных касаний) выдает трассу перемещения для каждого пальца. Отдельные пальцы или другие объекты, которые генерируют трассы перемещения, называются указателями (pointers). События перемещения содержат информацию о всех указателях, которые активны в настоящий момент, даже если некоторые из них не переместились с момента последнего полученного события.
Количество указателей всегда изменяется только на 1, когда отдельные указатели опускаются и поднимаются, за исключением случая отмены жеста.
Каждый указатель имеет уникальный идентификатор, который назначается при первом опускании (показывается кодом ACTION_DOWN или ACTION_POINTER_DOWN ). Идентификатор указателя остается валидными, пока указатель не поднимется (показывается кодом ACTION_UP или ACTION_POINTER_UP ), или когда жест отменен (показывается кодом ACTION_CANCEL ).
Класс MotionEvent предоставляет несколько методов для опроса позиции и других свойств указателей, такие как getX(int) , getY(int) , getAxisValue(int) , getPointerId(int) , getToolType(int) и многие другие. Большинство этих методов принимают индекс указателя в качестве параметра, а не идентификатор указателя. Индекс каждого указателя находится в диапазоне от 0 до getPointerCount() -1.
Заранее не определен порядок, в котором указатели появляются в событии перемещения. Таким образом индекс одного и того же указателя может поменяться от одного события к другому, но идентификатор указателя гарантированно останется неизменным, пока указатель остается активным. Используйте метод getPointerId(int), чтобы получить идентификатор указателя, и отслеживать его через последующие события перемещения в жесте. Тогда для последовательных событий перемещения используйте метод findPointerIndex(int), чтобы получить индекс указателя на предоставленный идентификатор указателя в этом событии перемещения.
Мышь и кнопки стилуса могут быть получены с использованием getButtonState() . Хорошая идея проверить состояние кнопки при обработки ACTION_DOWN как части события касания. Приложение может выполнять разные действия при появлении события касания, если событие касания сопровождается вторым нажатием на кнопку, как например вызов контекстного меню.
[Пакетная обработка (Batching)]
Для эффективности события перемещения с ACTION_MOVE могут группировать вместе несколько выборок перемещения в один объект (batch). Самые актуальные текущие координаты доступны через вызов getX(int) и getY(int). Предыдущие координаты в batch доступны через getHistoricalX(int, int) и getHistoricalY(int, int). Координаты будут «историческими» (historical) только потому, что они старше текущих координат в batch; однако они все равно более актуальные, чем другие координаты, которые были получены в других событиях перемещения. Чтобы обработать все координаты в batch с привязкой по времени, сначала рассмотрите historical-координаты и затем текущие координаты.
Пример, получение всех выборок для всех указателей в порядке по времени:
[Типы устройств]
Интерпретация содержимого MotionEvent значительно варьируется в зависимости от источника класса устройства.
Для устройств указания с исходным классом SOURCE_CLASS_POINTER , таких как тачскрины, координаты указателя показывают абсолютные позиции, такие как координаты X/Y представления. Каждый полный жест представлен последовательностью событий перемещения с действиями, которые описывают переходы состояний указателя и перемещения. Жест начинается с события перемещения ACTION_DOWN, которое предоставляет место первого опускания указателя. Для каждого дополнительного указателя, который опускается вниз или вверх, фреймворк будет генерировать событие перемещения с ACTION_POINTER_DOWN или ACTION_POINTER_UP соответственно. Перемещения указателя описаны в событиях перемещения с ACTION_MOVE. Окончание жеста происходит либо когда поднимается последний указатель (по событию перемещения с ACTION_UP), или когда жест отменен (с событием перемещения ACTION_CANCEL).
Некоторые устройства указания, такие как мыши, могут поддерживать вертикальную и/или горизонтальную прокрутку (scrolling). Событие прокрутки сообщается как обычное событие перемещений с ACTION_SCROLL , которое включает в себя смещение прокрутки в по осям AXIS_VSCROLL и AXIS_HSCROLL . См. описание getAxisValue(int) для дополнительной информации как получать эти дополнительные оси.
Устройства трекбол с исходным классом SOURCE_CLASS_TRACKBALL получают координаты указателя, которые задают относительное перемещение (изменение) по осям X/Y. Жест трекбола состоит из последовательности перемещений, описанных событиями перемещения с ACTION_MOVE, перемежающимися со случающимися событиями ACTION_DOWN или ACTION_UP, когда кнопки трекбола нажимаются или отпускаются.
Устройства джойстика с исходным классом SOURCE_CLASS_JOYSTICK , получают координаты указателя с абсолютной позицией по осям джойстика. Значения осей джойстика нормализуются к диапазону от -1.0 до 1.0, где 0.0 соответствует центральному положению. Больше информации по набору доступных осей и диапазону перемещений можно получить через getMotionRange(int). Общие оси джойстика: AXIS_X, AXIS_Y, AXIS_HAT_X, AXIS_HAT_Y, AXIS_Z и AXIS_RZ.
Обратитесь к InputDevice для дополнительной информации о различных видах устройств ввода, источниках, предоставляющих координаты указателя.
[Гарантии согласованности]
События перемещения всегда передаются в представления (view) как последовательный поток событий. Что из себя представляет последовательный поток — зависит от типа устройства. Для событий касания последовательность включает в себя информацию по опусканию указателей с привязкой ко времени, групповым перемещением, и затем с поднятием по одному или с отменой жеста.
Хотя фреймворк пытается передать непрерывный поток событий перемещения к элементам интерфейса (View), нет полной гарантии о передаче всех событий. Некоторые события могут быть отброшены или модифицированы элементами интерфейса в приложении до того, как будут доставлены, в результате чего поток событий будет неполным. Элементы интерфейса (View) должны быть всегда готовы к обработке ACTION_CANCEL и должны быть толерантны к аномальным ситуациям, таким как прием нового ACTION_DOWN без предварительного получения ACTION_UP для предыдущего жеста.
Полное описание констант и методов класса см. в [1].
[Пример: определение места касания экрана]
Для того, чтобы определить место касания экрана в программе Android, переопределите метод onTouchEvent для в классе Activity:
[Пример: определение места касания на виджете ImageView]
MotionEvent может использоваться для определения мест касания на изображении, чтобы по ним предпринимать различные действия. Простой пример — двухпозиционный выключатель, на левой картинке он в положении «OFF» (выключено), а на правой в положении «ON» (включено).
Идея состоит в следующем: при нажатии на верхнюю часть картинки выключатель должен «включаться» (т. е. должна показываться картинка, где выключатель в положении ON), а когда нажатие происходит на нижнюю часть картинки, то выключатель должен «выключаться» (должна показываться картинка, где выключатель в положении OFF). Далее процесс по шагам.
1. Создайте 2 картинки для состояний выключателя ON и OFF в виде файлов формата PNG, назовите эти файлы switch_on.png и switch_off.png соответственно. Положите их в папку res\drawable\ проекта. Сделайте Clean для проекта, чтобы в файле R.java сгенерировались идентификаторы для картинок.
2. Бросьте на форму программы виджет ImageView, дайте ему понятный идентификатор, например imageSwitch. В качестве источника картинки для ImageView укажите ресурс switch_off (это наша картинка для выключенного состояния выключателя). В результате в файле activity_main.xml появится определение наподобие следующего:
3. В обработчике в класс Activity программы добавьте переменную ImageView, и в обработчике onCreate сделайте инициализацию этой переменной, привязав её к добавленному виджету imageSwitch. Добавьте также для этой переменной обработчик события OnTouchListener. Вот полный код для onCreate активности:
Источник
Motion Events with Drag and Drop in Android
Jul 31 · 8 min read
This article covers important concepts about Motion Events with drag-drop of a view and related callbacks in Android.
The Android view system framework is a big topic to explain how internally works. Here in this article, I would like to cover the working example of dragging and dropping a view throughout the screen and the events callbacks of motion events.
First of all, we will examine at what is the significance of the motion events in Android.
Motion Event
To make it easy, when a n Android devices screen detects, the movement then the motion event callbacks occur, which executes few callbacks in the form of various actions. It also delivers a set for axis values about the contact area of the device screen.
As reflected in the above image, when the touch event is acted the action_down event will be executed and when the touch event is released the action_up event will be executed It will also obtain the X and Y coordinates according to the contact area.
How Touch System Works
To Understand the touch system in android, we have to understand three terms.
Activity Main View(decor View): The decor view is the main view of an activity that receives the touch input first and starts transferring the touch events to the respective view group.
View Groups: The View Group is a parent view group container of an XML associated with the activity. For example, LinearLayout, RelativeLayout
Views: The child views like buttons and text views contained by the parent view group in the activity XML file.
For example, we have an activity with a textview and the touch event is performed on the textview.
When the touch event is detected first it will be handled by Activity’s main view then it will be transferred to View Group container and then will be transferred to the respective view.
As per the view hierarchy of nasted view groups in xml file, there might be multiple event transfer in multiple view groups.
Call backs on event transfered
The entry point for the touch, press, and click motion event is the Activity decor view which contains all the view groups and views for further transfer of the motion event.
It does the transfer of events from parent view to child view using dispatchTouchEvent.
The dispatchTouchEvent is a call back method that gets called on each event transfer from parent view to child view in the view tree, so going ahead from the activity’s decor view to down in the view tree, the dispatchTouchEvent will be called.
Touch Event Handeling
An important thing to know here is how the current view or view group knows that the touch event will be handled in its child view, and it needs to transfer the event to its child.
During the transfer for touch event from parents view to its child view, there is one more callback method that will be executed, called onInterceptTouchEvent.
Note that onInterceptTouchEvent() is a method from the ViewGroup class, and not from Activity.
onInterceptTouchEvent method returns a boolean value true or false in different case.
Ture: When the event is not transferred to its child view and it is handled in the current view or view group itself.
So when the interceptTouchEvent returns True, the event will not be dispatched down in the tree further.
False: When the touch event is dispatched one by one down in the view tree, onInterceptTouchEvent will keep returning false.
In this case, the touch event is not handled in the current view, and it needs to pass to its child view in the view tree.
The touch system has one more important callback contrast to onInterceptTouchEvent that is onTouchEvent which also returns the boolean value. onTouchEvent callback works right opposite to onInterceptTouchEvent.
If onTouchEvent returns true that means the touch is been handled with the current view and if it returns false then the Event will be transferred to its parent view and this happens from bottom to top in the view tree.
As mention above, the motion event delivers various actions like action_up and action_down.
The action codes are constants that are available in the MotionEvent class.
After understanding the above concepts let’s do some sample codes to check the drag and drop feature and also check the use of MotionEvent Action codes.
Create an android Project and add the xml code to the main activity xml file.
This activity has dragme text which is used to perform the drag and drop functionality.
Step by step we will check the events and call back for MotionEvents!!
This is the activity code where I added the onTouchListener to the dragme Text view.
Let’s run the code and look at the logcat.
You can perform multiple operations on the dragme text and see the log cat here you will see the event logs with different codes delivered from the MotionEvent class.
If you see the code of MotionEvent class, you will found the meaning of these codes.
Now we will handle the action_down, action_down and anction_move event in the code.
Let’s run the code again and look at the logcat.
Try to drag the text, you will see the call back in a sequence, action_down once initially, action_up once at last and action_move multiple times in between.
Now we will see how to drag the view.
As mention above the MotionEvent class also deliver the X and Y axis for the view on which the event is performed. we can get the X and Y coordinates for the view using getX() and getY() methods.
So, in this case, the drag me text is the view that is handling the onTouchEvent, using the dragme text we can get the X and Y coordinate.
This will give you the initial X and Y cordinates of drag me text view.
To implement the drag and drop functionality, we will implement the below logic.
Here is the full Activity for the above explained logic.
Now we will drag and drop the text once and we will analyse the callback action for the drag event.
Lets understand the logs and call back action.
As mention above, the action_down will be called once initially, action_up will be called once at last, and action_move will be called multiple times in between.
Logs looks like this.
As we are calculating the distance and final coordinates with action_move that’s why the last coordinates are similar for action_move and action_up.
I hope the drag and drop functionality is working smoothly, and you enjoyed the article.
Here is the git link for complete code example.
Источник