Android2.1のマルチタッチの雰囲気プログラミング

せっかちな人(本人)向けテンプレート

public void mogemoge(MotionEvent event){
  int motion = event.getAction();
  int newPointerIndex = (motion & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;
  int newPointerID = event.getPointerId(newPointerIndex);
  int type = motion & MotionEvent.ACTION_MASK;
  
  int pointerCount = event.getPointerCount();
  
  switch(type){
  case MotionEvent.ACTION_MOVE:
    for (int i = 0; i < pointerCount; i++){
      updateSomething(event.getX(i), event.getY(i));
    }
    break;
  case MotionEvent.ACTION_UP:
    processUP(event.getX(), event.getY());
    break;
  case MotionEvent.ACTION_POINTER_UP:
    for (int i = 0; i < pointerCount; i++){
      if (i == newPointerIndex){
        processUP2(newPointerID, event.getX(i), event.getY(i));
      }
      updateSomething(event.getX(i), event.getY(i));
    }
    break;
  case MotionEvent.ACTION_DOWN:
    processDOWN(event.getX(), event.getY());
    break;
  case MotionEvent.ACTION_POINTER_DOWN:
    for (int i = 0; i < pointerCount; i++){
      if (i == newPointerIndex){
        processDOWN2(newPointerID, event.getX(i), event.getY(i));
      }
      updateSomething(event.getX(i), event.getY(i));
    }
    break;
  default:
    break;
  }
}

むかし

onTouchEvent()にMotionEventが飛んでくる.このイベントから,MotionEvent#getX(), MotionEvent#getY()メソッドによって指の現在地を取得できる.イベントの種類は下の3つ

  • ACTION_DOWN:指が押されたイベント.get[XY]()では押された位置が返る
  • ACTION_MOVE:押されていた指が動いたイベント.get[XY]()では指の現在地が返る
  • ACTION_UP:指が離れたイベント.get[XY]()では指が最後にいた位置が返る

2.1で変わったところ

MotionEventの中身が変わった

  • 飛ばされてきたMotionEventが複数の指の座標を持つようになった
    • いくつ持つかはMotionEvent#getPoinerCount()で取得
  • 各指は以前と同じx, y座標に加え,指毎のIDを持つ
    • 各指のID・座標は,MotionEvent#getID(int i), MotionEvent#get[XY](int i)により取得できる.引数は0〜getPoinerCount()-1までの整数
      • get[XY]()も残っている.これはget[XY](0)に等しい

イベントの種類も増え,以前から存在するイベントも意味が変わった

  • ACTION_DOWN:一本目の指が押されたイベント.get[XY]()の挙動は変わらない.引数つきでも押されている指は一本なので扱いは変わらない
  • ACTION_MOVE:全ての指が離れることなく,かつ最低でも一本が動いたイベント.get[XY](int i)により前指の現在地が返る
  • ACTION_UP:最後の一本の指が離れたイベント.ACTION_UPに同じ
  • ACTION_POINTER_DOWN:何本かが押されている状況で,一本指が追加で押されたイベント.ACTION_MOVEと同じくget[XY](int i)により各指の現在地が返る
  • ACTION_POINTER_UP:何本かが押されている状況で,一本のみが離れたイベント.ACTION_MOVEと同じくget[XY](int i)により各指の現在地が返る

最後にいっこ

  • イベントの種類の取得方法が変わった
int type = motion & MotionEvent.ACTION_MASK;

ACTION_POINTER_UP,ACTION_POINTER_DOWNでの押された・離れた指の取得

ACTION_POINTER_UP,ACTION_POINTER_DOWNは,一本の指が押されたり離れたりしたことを表している.複数押されているうちのどの指がイベントを起こしたかは,次のように指のIDを取得することで調べることができる

int index = (motion & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;
int id = event.getPointerId(index);
for (int i = 0, max = event.getPointerCount(); i < max; i++){
  if (event.getID(i) == id){
    // お前か!
  }
}