MotionEvent事件对象
一般我们是在View的onTouchEvent方法中处理MotionEvent对象的.
public boolean onTouchEvent(MotionEvent event)
在这里我们需要从一个MotionEvent对象中获得哪些信息呢?
(1)首先应该是事件的类型吧?
可以通过getAction(),在android2.2之后加入多点触控支持之后使用getActionMasked()方法 或者 int action = event.getAction() & ACTION_MASK.
主要的事件类型有:
ACTION_DOWN: 表示用户开始触摸.
ACTION_MOVE: 表示用户在移动(手指或者其他)
ACTION_UP:表示用户抬起了手指
ACTION_CANCEL:表示手势被取消了,一些关于这个事件类型的讨论见:http://stackoverflow.com/questions/11960861/what-causes-a-motionevent-action-cancel-in-android
还有一个不常见的:
ACTION_OUTSIDE: 表示用户触碰超出了正常的UI边界.
但是对于多点触控的支持,Android加入了以下一些事件类型.来处理,如另外有手指按下了,
有的手指抬起来了.等等:
ACTION_POINTER_DOWN:有一个非主要的手指按下了.
ACTION_POINTER_UP:一个非主要的手指抬起来了
(2)事件发生的位置,x,y轴
getX() 获得事件发生时,触摸的中间区域在屏幕的X轴.
getY() 获得事件发生时,触摸的中间区域在屏幕的X轴.
在多点触控中还可以通过:
getX(int pointerIndex) ,来获得对应手指事件的发生位置. 获得Y轴用getY(int pointerIndex)
(3)其他属性
getEdgeFlags():当事件类型是ActionDown时可以通过此方法获得,手指触控开始的边界. 如果是的话,有如下几种值:EDGE_LEFT,EDGE_TOP,EDGE_RIGHT,EDGE_BOTTOM
掩码常量
ACTION_MASK = 0X000000ff动作掩码
ACTION_POINTER_INDEX_MASK = 0X0000ff00触摸点索引掩码
相关方法
getAction()方法返回的是int类型,用到的只有低16位,其中:低八位是动作的类型,高8位是触摸点索引值的表示(单点为0,双点为1)
获得动作类型: int action = event.getAction() & ACTION_MASK 或者使用 getActionMasked()
获得触摸点索引类型: int pointerIndex = (event.getAction() & ACTION_POINTER_INDEX_MASK ) >> ACTION_POINTER_INDEX_SHIFT
或者使用 getActionIndex()
为什么要有索引信息?
有了索引信息,我们可以在onTOuchEvent事件中判断传进来的MotionEvent对象对应的是单点信息还是多点信息。
getX()和getRawX()的区别
getX()是表示Widget相对于自身左上角的x坐标
java.lang.Object | ||
↳ | android.view.InputEvent | |
↳ | android.view.MotionEvent |
Class Overview
Object used to report movement (mouse, pen, finger, trackball) events. Motion events may hold either absolute or relative movements and other data, depending on the type of device.
Overview
Motion events describe movements in terms of an action code and a set of axis values. The action code specifies the state change that occurred such as a pointer going down or up. The axis values describe the position and other movement properties.
For example, when the user first touches the screen, the system delivers a touch event to the appropriate View
with the action code ACTION_DOWN
and a set of axis values that include the X and Y coordinates of the touch and information about the pressure, size and orientation of the contact area.
Some devices can report multiple movement traces at the same time. Multi-touch screens emit one movement trace for each finger. The individual fingers or other objects that generate movement traces are referred to aspointers. Motion events contain information about all of the pointers that are currently active even if some of them have not moved since the last event was delivered.
The number of pointers only ever changes by one as individual pointers go up and down, except when the gesture is canceled.
Each pointer has a unique id that is assigned when it first goes down (indicated by ACTION_DOWN
or ACTION_POINTER_DOWN
). A pointer id remains valid until the pointer eventually goes up (indicated by ACTION_UP
orACTION_POINTER_UP
) or when the gesture is canceled (indicated by ACTION_CANCEL
).
The MotionEvent class provides many methods to query the position and other properties of pointers, such as getX(int)
, getY(int)
, getAxisValue(int)
, getPointerId(int)
, getToolType(int)
, and many others. Most of these methods accept the pointer index as a parameter rather than the pointer id. The pointer index of each pointer in the event ranges from 0 to one less than the value returned by getPointerCount()
.
The order in which individual pointers appear within a motion event is undefined. Thus the pointer index of a pointer can change from one event to the next but the pointer id of a pointer is guaranteed to remain constant as long as the pointer remains active. Use the getPointerId(int)
method to obtain the pointer id of a pointer to track it across all subsequent motion events in a gesture. Then for successive motion events, use thefindPointerIndex(int)
method to obtain the pointer index for a given pointer id in that motion event.
Mouse and stylus buttons can be retrieved using getButtonState()
. It is a good idea to check the button state while handling ACTION_DOWN
as part of a touch event. The application may choose to perform some different action if the touch event starts due to a secondary button click, such as presenting a context menu.
Batching
For efficiency, motion events with ACTION_MOVE
may batch together multiple movement samples within a single object(多点触控的关键点). The most current pointer coordinates are available using getX(int)
and getY(int)
. Earlier coordinates within the batch are accessed using getHistoricalX(int, int)
and getHistoricalY(int, int)
. The coordinates are "historical" only insofar as they are older than the current coordinates in the batch; however, they are still distinct from any other coordinates reported in prior motion events. To process all coordinates in the batch in time order, first consume the historical coordinates then consume the current coordinates.
Example: Consuming all samples for all pointers in a motion event in time order.
void printSamples(MotionEvent ev) {
final int historySize = ev.getHistorySize();
final int pointerCount = ev.getPointerCount();
for (int h = 0; h < historySize; h++) {
System.out.printf("At time %d:", ev.getHistoricalEventTime(h));
for (int p = 0; p < pointerCount; p++) {
System.out.printf(" pointer %d: (%f,%f)",
ev.getPointerId(p), ev.getHistoricalX(p, h), ev.getHistoricalY(p, h));
}
}
System.out.printf("At time %d:", ev.getEventTime());
for (int p = 0; p < pointerCount; p++) {
System.out.printf(" pointer %d: (%f,%f)",
ev.getPointerId(p), ev.getX(p), ev.getY(p));
}
}
Device Types
The interpretation of the contents of a MotionEvent varies significantly depending on the source class of the device.
On pointing devices with source class SOURCE_CLASS_POINTER
such as touch screens, the pointer coordinates specify absolute positions such as view X/Y coordinates. Each complete gesture is represented by a sequence of motion events with actions that describe pointer state transitions and movements. A gesture starts with a motion event with ACTION_DOWN
that provides the location of the first pointer down. As each additional pointer that goes down or up, the framework will generate a motion event with ACTION_POINTER_DOWN
or ACTION_POINTER_UP
accordingly. Pointer movements are described by motion events with ACTION_MOVE
. Finally, a gesture end either when the final pointer goes up as represented by a motion event with ACTION_UP
or when gesture is canceled with ACTION_CANCEL
.
Some pointing devices such as mice may support vertical and/or horizontal scrolling. A scroll event is reported as a generic motion event with ACTION_SCROLL
that includes the relative scroll offset in the AXIS_VSCROLL
andAXIS_HSCROLL
axes. See getAxisValue(int)
for information about retrieving these additional axes.
On trackball devices with source class SOURCE_CLASS_TRACKBALL
, the pointer coordinates specify relative movements as X/Y deltas. A trackball gesture consists of a sequence of movements described by motion events withACTION_MOVE
interspersed with occasional ACTION_DOWN
or ACTION_UP
motion events when the trackball button is pressed or released.
On joystick devices with source class SOURCE_CLASS_JOYSTICK
, the pointer coordinates specify the absolute position of the joystick axes. The joystick axis values are normalized to a range of -1.0 to 1.0 where 0.0 corresponds to the center position. More information about the set of available axes and the range of motion can be obtained using getMotionRange(int)
. Some common joystick axes are AXIS_X
, AXIS_Y
, AXIS_HAT_X
,AXIS_HAT_Y
, AXIS_Z
and AXIS_RZ
.
Refer to InputDevice
for more information about how different kinds of input devices and sources represent pointer coordinates.
Consistency Guarantees
Motion events are always delivered to views as a consistent stream of events. What constitutes a consistent stream varies depending on the type of device. For touch events, consistency implies that pointers go down one at a time, move around as a group and then go up one at a time or are canceled.
While the framework tries to deliver consistent streams of motion events to views, it cannot guarantee it. Some events may be dropped or modified by containing views in the application before they are delivered thereby making the stream of events inconsistent. Views should always be prepared to handle ACTION_CANCEL
and should tolerate anomalous situations such as receiving a new ACTION_DOWN
without first having received anACTION_UP
for the prior gesture.