Androidアプリ開発入門のFAQとおすすめアンドロイドアプリ・ゲーム紹介サイトです。

onTouchEvent()メソッド(マルチタッチ)

2011年9月27日(火) 4:23 PM

マルチタッチを使って、タッチしたところに赤色と青色の丸を描画するサンプルを作ってみました。

画面をタッチすると、赤や青の丸が描画される。(イメージ)
MultiTouch1
タッチしたまま移動すると、丸もそれに合わせて移動する(イメージ)
MultiTouch2
画面から手を放すと丸が消えてしまう(イメージ)
MultiTouch3

マルチタッチを使うには、onTouchEvent()内の処理を以下のようにします。

public boolean onTouchEvent(MotionEvent event) {

int action = event.getAction();
int index = (action & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;
int eventID = event.getPointerId(index);
int touchCount = event.getPointerCount();

switch ( action & MotionEvent.ACTION_MASK ) {

case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
//画面がタッチされたときの動作
break;

case MotionEvent.ACTION_MOVE:
//タッチしたまま移動したときの動作
break;

case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
//タッチが離されたときの動作
break;
}

説明
int action = event.getAction();
アクション情報を取得する。

int index = (action & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;
イベントID(PointerId)のためのインデックスを取得する.(マルチタッチでは、複数箇所タッチされた時のために、インデックスが割り当てられます。)

int eventID = event.getPointerId(index);
インデックスを引数にして、イベントID(PointerId)を取得する。(イベントIDによって、複数箇所タッチされていても、どのタッチ情報なのかを識別することができる。)

int touchCount = event.getPointerCount();
タッチ(インデックス)の数を取得する。

ACTION_POINTER_DOWN: タッチパネルの一箇所以上をタッチしている状態で、さらにタッチパネルを押した場合
ACTION_POINTER_UP: タッチパネルの二箇所以上をタッチしている状態で、うち一箇所を離した場合
ACTION_DOWN: タッチパネルがまだタッチされていない状態で、タッチパネルを押した場合
ACTION_MOVE: タッチパネルを押したままスライドさせた場合
ACTION_UP: タッチパネルがまだタッチされていない状態で、タッチパネルから指を持ち上げた場合

*マルチタッチはAndroid2.1(2.0)以降にしか対応していません。

◆ブログ記事「カスタムViewの実装の仕方」のサンプルに、マルチタッチ機能を加えてみました。

*変更点
①「CustomView.java」にマルチタッチ機能を実装。
onTouchEvent()内にinvalidate();を加えていないと、再描画されないみたいなので注意です。
②「SampleThree.java」に、View側からキーイベントを取得できるように、
view.setFocusable(true);
view.setFocusableInTouchMode(true);
を加えました。

「CustomView.java」のソースコード


package com.appliinfo.android.samplethree;

import java.util.HashMap;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

public class CustomView extends View
{
	private Context mContext;
	private Paint mCirclePaint1 = new Paint();
	private Paint mCirclePaint2 = new Paint();
    private HashMap points=new HashMap();
    public int redID = -1;
    public int blueID = -1;

	//コンストラクタ
	public CustomView(Context context) {
		super(context);
		mContext = context;
	}

	public CustomView(Context context, AttributeSet attrs) {
		super(context, attrs);
		mContext = context;
	}

	@Override
	protected void onDraw(Canvas canvas)
	{
		super.onDraw(canvas);

		Point circlePt;

		//ペイントの色とスタイルをセット(色:赤色 スタイル:図形の中を塗りつぶす)
		mCirclePaint1.setARGB(255, 255, 153, 153);
		mCirclePaint1.setStyle(Paint.Style.FILL);

		//ペイントの色とスタイルをセット(色:青色 スタイル:図形の中を塗りつぶす)
		mCirclePaint2.setARGB(255, 153, 204, 255);
		mCirclePaint2.setStyle(Paint.Style.FILL);

		canvas.drawColor(Color.WHITE);

		if(points.containsKey(redID)) {

			circlePt = points.get(redID);
			//画面の中心に円を描く
				canvas.drawCircle(circlePt.x, circlePt.y, 25, mCirclePaint1);
		}

		if(points.containsKey(blueID)) {

			circlePt = points.get(blueID);
			//画面の中心に円を描く
			canvas.drawCircle(circlePt.x, circlePt.y, 25, mCirclePaint2);
		}

	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {

	    int action = event.getAction();
	    int index = (action & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;
	    int touchCount = event.getPointerCount();
	    int eventID = event.getPointerId(index);

		switch ( action & MotionEvent.ACTION_MASK ) {

		case MotionEvent.ACTION_DOWN:
		case MotionEvent.ACTION_POINTER_DOWN:
			//画面がタッチされたときの動作

			int tx =(int)event.getX(index);
			int ty =(int)event.getY(index);

			//タッチされた座標を取得
			Point posTouch = new Point(tx, ty);
				if(posTouch != null) {

					if(redID == -1) {
						redID = eventID;
					}
					else if(blueID == -1) {
						blueID = eventID;
					}
					//イベントIDとその座標を保存
					points.put(eventID, posTouch);
				}

			break;

		case MotionEvent.ACTION_MOVE:
			//タッチしたまま移動したときの動作

			for(index = 0; index < touchCount; index++) {

			    int eventID2 = event.getPointerId(index);
				int tx2 =(int)event.getX(index);
				int ty2 =(int)event.getY(index);

				//タッチされた座標を取得
				Point posTouch2 = new Point(tx2, ty2);

				if(points.containsKey(eventID2)) {

					if(posTouch2 != null) {
						//イベントIDとその座標を保存
						points.put(eventID2, posTouch2);
					}

				}
			}

			break;

		case MotionEvent.ACTION_UP:
		case MotionEvent.ACTION_POINTER_UP:
			//タッチが離されたときの動作

			int tx3 =(int)event.getX(index);
			int ty3 =(int)event.getY(index);

			//タッチされた座標を取得
			Point posTouch3 = new Point(tx3, ty3);

			if(points.containsKey(eventID)) {

				if(eventID == redID) {
					redID = -1;
				}
				else if(eventID == blueID) {
					blueID = -1;
				}

				//イベントIDとその座標を消去
				points.remove(eventID);
			}

			break;
		}

		invalidate();

		return true;
	}

}


「SampleThree.java」のサンプルコード

package com.appliinfo.android.samplethree;

import android.app.Activity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;

public class SampleThree extends Activity {

    /** Called when the activity is first created. */

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        LayoutInflater factory = LayoutInflater.from(this);

        // Set game layout
        View view = factory.inflate(R.layout.main, null);
        setContentView(view);

        // Enable view key events
		view.setFocusable(true);
		view.setFocusableInTouchMode(true);

    }
}

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

コメントの更新情報

トラックバックURL

http://www.appli-info.jp/archives/911/trackback

* RSS FEED

広告