以前的文章層從Framework層介紹了Android Touch事件即(MotionEvent)的傳遞機制。本文將詳細介紹MotionEvent的一些成員和方法。瞭解了MotionEvent對開發一些特效如拖動控件或多點縮放控件有很大的做用。同時,掌握MotionEvent類也是學好android觸控技術的基礎。java
1、一些常量android
常見的動做常量:ide
public static final int ACTION_DOWN = 0;單點觸摸動做fetch
public static final int ACTION_UP = 1;單點觸摸離開動做
public static final int ACTION_MOVE = 2;觸摸點移動動做
public static final int ACTION_CANCEL = 3;觸摸動做取消
public static final int ACTION_OUTSIDE = 4;觸摸動做超出邊界
public static final int ACTION_POINTER_DOWN = 5;多點觸摸動做
public static final int ACTION_POINTER_UP = 6;多點離開動做
如下是一些非touch事件
public static final int ACTION_HOVER_MOVE = 7;
public static final int ACTION_SCROLL = 8;
public static final int ACTION_HOVER_ENTER = 9;
public static final int ACTION_HOVER_EXIT = 10;
this
掩碼常量spa
ACTION_MASK = 0X000000ff動做掩碼
ACTION_POINTER_INDEX_MASK = 0X0000ff00觸摸點索引掩碼
.net
ACTION_POINTER_INDEX_SHIFT = 8 獲取觸摸點索引須要移動的位數
orm
另注:對於TextView來講,只有Action_DOWN能被檢測,Action_up, action_cancel都檢測不到,講TextView控件換成Button則都能檢測到MotionEvent事件。通常action_cancel事件必須實現,由於當快速滑過button時,action_up則不被檢測執行,須要action_cancel來執行事件。對象
2、相關方法blog
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對象對應的是單點信息仍是多點信息。
下面的代碼段能使用戶在屏幕上拖動一個對象。它記錄了初始點的位置,計算點移動的距離,並將對象移動到新的位置。它正確的處理了這種狀況:當第一個手指把控件拖到一個位置,而後按下第二個手指,且第二個手指與同一個控件上。當用戶擡起第一個手指時,控件不會跑到第二個手指的位置同時第二個手指能夠繼續拖動控件。
[java] view plaincopy
// The ‘active pointer’ is the one currently moving our object.
private int mActivePointerId = INVALID_POINTER_ID;
@Override
public boolean onTouchEvent(MotionEvent ev) {
// Let the ScaleGestureDetector inspect all events.
mScaleDetector.onTouchEvent(ev);
final int action = MotionEventCompat.getActionMasked(ev);
switch (action) {
case MotionEvent.ACTION_DOWN: {
final int pointerIndex = MotionEventCompat.getActionIndex(ev);
final float x = MotionEventCompat.getX(ev, pointerIndex);
final float y = MotionEventCompat.getY(ev, pointerIndex);
// Remember where we started (for dragging)
mLastTouchX = x;
mLastTouchY = y;
// Save the ID of this pointer (for dragging)
mActivePointerId = MotionEventCompat.getPointerId(ev, 0);
break;
}
case MotionEvent.ACTION_MOVE: {
// Find the index of the active pointer and fetch its position
final int pointerIndex =
MotionEventCompat.findPointerIndex(ev, mActivePointerId);
final float x = MotionEventCompat.getX(ev, pointerIndex);
final float y = MotionEventCompat.getY(ev, pointerIndex);
// Only move if the ScaleGestureDetector isn't processing a gesture.
if (!mScaleDetector.isInProgress()) {
// Calculate the distance moved
final float dx = x - mLastTouchX;
final float dy = y - mLastTouchY;
mPosX += dx;
mPosY += dy;
invalidate();
}
// Remember this touch position for the next move event
mLastTouchX = x;
mLastTouchY = y;
break;
}
case MotionEvent.ACTION_UP: {
mActivePointerId = INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_CANCEL: {
mActivePointerId = INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_POINTER_UP: {
final int pointerIndex = MotionEventCompat.getActionIndex(ev);
final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex);
if (pointerId == mActivePointerId) {
// This was our active pointer going up. Choose a new
// active pointer and adjust accordingly.
final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
mLastTouchX = MotionEventCompat.getX(ev, newPointerIndex);
mLastTouchY = MotionEventCompat.getY(ev, newPointerIndex);
mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex);
}
break;
}
}
return true;
}
MotionEvent還包含了移動操做中其它歷史移動數據以方便處理觸控的移動操做.
android sdk對於這個類的描述中就有這麼一句:
For efficiency, motion events with ACTION_MOVE may batch together multiple movement samples within a single object.