Android觸控基礎:MotionEvent

以前的文章層從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

  1. // The ‘active pointer’ is the one currently moving our object.  

  2. private int mActivePointerId = INVALID_POINTER_ID;  

  3.   

  4. @Override  

  5. public boolean onTouchEvent(MotionEvent ev) {  

  6.     // Let the ScaleGestureDetector inspect all events.  

  7.     mScaleDetector.onTouchEvent(ev);  

  8.                

  9.     final int action = MotionEventCompat.getActionMasked(ev);   

  10.           

  11.     switch (action) {   

  12.     case MotionEvent.ACTION_DOWN: {  

  13.         final int pointerIndex = MotionEventCompat.getActionIndex(ev);   

  14.         final float x = MotionEventCompat.getX(ev, pointerIndex);   

  15.         final float y = MotionEventCompat.getY(ev, pointerIndex);   

  16.               

  17.         // Remember where we started (for dragging)  

  18.         mLastTouchX = x;  

  19.         mLastTouchY = y;  

  20.         // Save the ID of this pointer (for dragging)  

  21.         mActivePointerId = MotionEventCompat.getPointerId(ev, 0);  

  22.         break;  

  23.     }  

  24.               

  25.     case MotionEvent.ACTION_MOVE: {  

  26.         // Find the index of the active pointer and fetch its position  

  27.         final int pointerIndex =   

  28.                 MotionEventCompat.findPointerIndex(ev, mActivePointerId);    

  29.               

  30.         final float x = MotionEventCompat.getX(ev, pointerIndex);  

  31.         final float y = MotionEventCompat.getY(ev, pointerIndex);  

  32.               

  33.         // Only move if the ScaleGestureDetector isn't processing a gesture.  

  34.         if (!mScaleDetector.isInProgress()) {  

  35.             // Calculate the distance moved  

  36.             final float dx = x - mLastTouchX;  

  37.             final float dy = y - mLastTouchY;  

  38.   

  39.             mPosX += dx;  

  40.             mPosY += dy;  

  41.   

  42.             invalidate();  

  43.         }  

  44.         // Remember this touch position for the next move event  

  45.         mLastTouchX = x;  

  46.         mLastTouchY = y;  

  47.   

  48.         break;  

  49.     }  

  50.               

  51.     case MotionEvent.ACTION_UP: {  

  52.         mActivePointerId = INVALID_POINTER_ID;  

  53.         break;  

  54.     }  

  55.               

  56.     case MotionEvent.ACTION_CANCEL: {  

  57.         mActivePointerId = INVALID_POINTER_ID;  

  58.         break;  

  59.     }  

  60.           

  61.     case MotionEvent.ACTION_POINTER_UP: {  

  62.               

  63.         final int pointerIndex = MotionEventCompat.getActionIndex(ev);   

  64.         final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex);   

  65.   

  66.         if (pointerId == mActivePointerId) {  

  67.             // This was our active pointer going up. Choose a new  

  68.             // active pointer and adjust accordingly.  

  69.             final int newPointerIndex = pointerIndex == 0 ? 1 : 0;  

  70.             mLastTouchX = MotionEventCompat.getX(ev, newPointerIndex);   

  71.             mLastTouchY = MotionEventCompat.getY(ev, newPointerIndex);   

  72.             mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex);  

  73.         }  

  74.         break;  

  75.     }  

  76.     }         

  77.     return true;  

  78. }  


MotionEvent還包含了移動操做中其它歷史移動數據以方便處理觸控的移動操做.

android sdk對於這個類的描述中就有這麼一句:

For efficiency, motion events with ACTION_MOVE may batch together multiple movement samples within a single object.
相關文章
相關標籤/搜索