MotionEventでマルチタッチを検出する
|MotionEventが改善され、ポインタIDが追加されました。IDで判別することで個々の指の動きを簡単に知ることができます。タッチイベントの検出・取得についてはタッチイベントを取得する(onTouchEventとMotionEvent)で解説しています。
マルチタッチの判別(ポインタIDの判別)
メソッド | 概要 |
---|---|
int getPointerCount() | MotionEventでの通知ポインタ数(n) |
int getPointerId(int pointerIndex) | PointerIDの取得(Indexは0からn-1まで) |
int findPointerIndex(int pointerId) | PointerIDからポインタを特定する |
MotionEventのマルチタッチ(PointerID関連)にかかわるメソッドの一部です。MotionEventについて詳細を把握されている場合、次の「MotionEvent通知タイミングと内容」を読み飛ばしても大丈夫です。「サンプルコード」を参照してください。
またAndroid 2.3から追加されたInputEventで入力デバイスが分かるようになっており、デバイス管理が改善されています(InputEventは改めて紹介予定)
MotionEvent通知タイミングと内容
MotionEventはタッチスクリーン、トラックボールなどのポインティングデバイスの動き、変化を検知してActivity,Viewなどに通知されるイベントです。ポインティングデバイスは各種デバイスで特性が異なるため、MotionEventは特性を吸収する役割も持っています。
MotionEvent.getAction()で取得できる動作
この中では ACTION_OUTSIDE が見慣れませんが、Viewの範囲外をタッチした場合に呼ばれます
定数名 | 説明 |
---|---|
ACTION_DOWN | 0x02 タッチ押下 |
ACTION_MOVE | 0x00 指を持ち上げずにスライドさせた場合 |
ACTION_UP | 0x01 指を持ち上げた場合 |
ACTION_CANCEL | 0x03 UP+DOWNの同時発生(=キャンセル)の場合 |
ACTION_OUTSIDE | 0x04 ターゲットとするUIの範囲外を押下 |
タッチスクリーン/タッチパネル
タッチスクリーンの場合はポインタ座標をX/Yの(Pixelに対する)絶対位置で検知できます。
ジェスチャー(指、マウス、トラックボールなどの)での押下はACTION_DOWNモーションイベントが発行されます。
移動中はACTION_MOVE、ジェスチャの最後、指が離されたときに、
ACTION_UPもしくはジェスチャがキャンセルと(フレームワーク側が)見なしたときは、ACTION_CANCELを通知します
トラックボール/マウス
トラックボールでは、ポインタ座標はX/Yの相対座標(移動量)で検知しています。
回転でACTION_MOVEイベントが通知されます(移動量)、タッチスクリーンと同様に押下でACTION_DOWN、
離したときにACTION_UPです。
サンプルコード
@Override public boolean onTouchEvent(MotionEvent event) { Log.d("TouchEvent", "X:" + event.getX() + ",Y:" + event.getY()); int historySize = event.getHistorySize(); //ACTION_MOVEイベントの数 int pointerCount = event.getPointerCount(); //イベントの発生時刻 Log.d("TouchEvent", "event time: "+ event.getEventTime()); //ポインタIDの取得、ポインタ座標 for (int p = 0; p < pointerCount; p++) { Log.d("TouchEvent", "Pointer ID :"+ event.getPointerId(p) + " X " + event.getX(p) + " , " + "Y " + event.getY(p) + " , " ); } //イベント履歴 for (int h = 0; h < historySize; h++) { Log.d("TouchEventHist", "event time: "+ event.getHistoricalEventTime(h)); for (int p = 0; p < pointerCount; p++) { Log.d("TouchEventHist", "Pointer ID :"+ event.getPointerId(p) + " X " + event.getHistoricalX(p, h) + " , " + "Y " + event.getHistoricalY(p, h) + " , " ); } } return true; }
ActivityのonTouchEventです。13行目では、getPointerIdでポインタIDを取得しています。
getX,getYメソッドにポインタIDを引数として渡して、座標を取得します。
23,24行目、イベント履歴の検出でも同様に第1引数をポインタIDで与えてポインタの座標を取得しています。
マルチタッチの判別(ポインタIDの判別)
メソッド | 概要 |
---|---|
int getPointerCount() | MotionEventでの通知ポインタ数(n) |
int getPointerId(int pointerIndex) | PointerIDの取得(Indexは0からn-1まで) |
int findPointerIndex(int pointerId) | PointerIDからポインタを特定する |
MotionEventのマルチタッチ(PointerID関連)メソッドです。ポインタIDを使えば次回のonTouchEvent以降も同じ動きを検出できます。
特定の動きを追いたいときはgetPointerIdメソッドでポインタIDを保持し、ポインタIDを引数にMotionEvent#findPointerIndexメソッドを利用すれば該当するPointerIndexがわかります(サンプルコードでの変数pにあたります)。
サンプルコードの出力例
12-13 22:01:07.736: DEBUG/TouchEvent(338): event time: 135563 12-13 22:01:07.736: DEBUG/TouchEvent(338): Pointer ID :0 X 97.0 , Y 309.0 12-13 22:01:07.745: DEBUG/TouchEventHist(338): event time: 135492 12-13 22:01:07.745: DEBUG/TouchEventHist(338): Pointer ID :0 X 96.0 , Y 306.0