2012年07月10日

マルチタッチイベントを取得する


今回はタッチの応用系マルチタッチイベントです
マルチタッチとはその名の通り2点以上を同時にタッチしたものを検出することです
Androidでは 2.0(API 5)以降でマルチタッチがサポートされ使用可能です

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

つまり複数の指でタッチパネルを操作するとタッチイベント(Touch Event)が
1点目タッチ:ACTION_DOWN
2点目タッチ:ACTION_POINTER_DOWN
ACTION_MOVE(繰返し)→
2点目離し:ACTION_POINTER_UP
1点目離し:ACTION_UP
の順に発生します

イベントをアクティビティで取得する
複数タッチイベントもアクティビティ内で取得する方法と
View内で取得する方法の2種類があります

今回はアクティビティ内で取得します
基本的にはアクティビティ内でTouchEventを取得するものの応用編となります
主な項目のみ挙げると
まずonTouchEventを作成します

getActionでどのようなタッチアクションをしたかの情報を取得します
getPointerCounではタッチ数を取得します

そしてタッチアクション情報をMotionEvent.ACTION_POINTER_ID_MASKでマスクして
MotionEvent.ACTION_POINTER_ID_SHIFT分シフトすることで
ポインタIDを取得するためのインデックスを取得しています
“>>”の記号はビット操作演算子と言われていて
ビット列を右や左にシフトします

getX・getYではタッチされたx・y座標を取得しています


今回はそれぞれのアクションイベントとポイント座標をログとして出力しています
MainActivity.java
package blog.test;
 


import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;

public class MainActivity extends Activity {
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		//タッチアクションの情報を取得
		int action = event.getAction();
		//タッチ数を取得
		int count = event.getPointerCount();
		
		int id = (action & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;
		
		//イベントごとにログを出力
		switch(action & MotionEvent.ACTION_MASK) {
		case MotionEvent.ACTION_DOWN:
			Log.i("tag", "Touch Down" + " count=" + count + ", id=" + id);
			break;
		case MotionEvent.ACTION_POINTER_DOWN:
			Log.i("tag", "Touch PTR Down" + " count=" + count + ", id=" + id);
			break;
		case MotionEvent.ACTION_UP:
			Log.i("tag", "Touch Up" + " count=" + count + ", id=" + id);
			break;
		case MotionEvent.ACTION_POINTER_UP:
			Log.i("tag", "Touch PTR Up" + " count=" + count + ", id=" + id);
			break;
		case MotionEvent.ACTION_MOVE:
			Log.i("tag", "Touch Move" + " count=" + count + ", id=" + id);
			break;
		}
		
		for(int i=0; i<count; i++) {
			Log.i("tag", " X=" + event.getX(i) + ", Y=" + event.getY(i) + ", id=" + event.getPointerId(i) );
		}
		return super.onTouchEvent(event);
	}
}

今回は実機のgalaxy sで実行してみました


いろいろタッチしてみるとマルチタッチにより次々にログが検出されているのがわかります
device129.png

スポンサードリンク

posted by kenken at 16:17 | Comment(0) | TrackBack(0) | イベント イベント処理 | このブログの読者になる | 更新情報をチェックする
2012年06月20日

複雑なタッチイベントを制御する


タッチパネルを操作するとTouch Eventが発生し
"Touch Down"・"move"・ "Touch Up"などがよばれるため
基本的な動作はここで処理することができます
タッチイベントを取得する
"ダブルタップ", "ロングタップ", "フリック"など少し複雑なタッチイベントを処理するには
SimpleOnGestureListenerを使います

複雑なタッチイベントを取得
実際のタッチイベントの取得方法ですが
まずはGestureDetectorを生成します
これはActivity内で構いません

次にonTouchEventを作成しタッチイベントを検出させます
そしてonTouchEventが発生するとGestureDetectorが発生するようにします

最後にあらかじめonGestureListenerを作っておき
onTouchEventが発生するとonGestureListener内で複雑なタッチイベントを検出します

言葉で書くと少し複雑ですがonTouchEventでは複雑なタッチイベントを特定できないため
onGestureListenerで判別するという方法です
実際のプログラムは以下のようになります
それぞれのタッチ動作の後にログを出力するようにしています

MainActivity.java
package blog.test;
 

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.GestureDetector.SimpleOnGestureListener;

public class MainActivity extends Activity {
	private GestureDetector gesDetect;
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		// GestureDetecotorのインスタンス生成
		gesDetect = new GestureDetector(this, onGestureListener);
	}

@Override
	public boolean onTouchEvent(MotionEvent event) {
	// タッチイベントが発生するとGestureDetectorが発生
	gesDetect.onTouchEvent(event);
	return false;
	}

	// 複雑なタッチイベントを取得
	private final SimpleOnGestureListener onGestureListener = new SimpleOnGestureListener() {
		@Override
		public boolean onDoubleTap(MotionEvent e) {
			Log.i("tag", "onDoubleTap");
			return super.onDoubleTap(e);
		}
		
		@Override
		public boolean onDoubleTapEvent(MotionEvent e) {
			Log.i("tag", "onDoubleTapEvent");
			return super.onDoubleTapEvent(e);
		}
		
		@Override
		public boolean onDown(MotionEvent e) {
			Log.i("tag", "onDown");
			return super.onDown(e);
		}

		@Override
		public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,float velocityY) {
			Log.i("tag", "onFling");
			return super.onFling(e1, e2, velocityX, velocityY);
		}
		
		@Override
		public void onLongPress(MotionEvent e) {
			Log.i("tag", "onLongPress");
			super.onLongPress(e);
		}
		
		@Override
		public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
			Log.i("tag", "onScroll");
			return super.onScroll(e1, e2, distanceX, distanceY);
		}
		
		@Override
		public void onShowPress(MotionEvent e) {
			Log.i("tag", "onShowPress");
			super.onShowPress(e);
		}
		
		@Override
		public boolean onSingleTapConfirmed(MotionEvent e) {
			Log.i("tag", "onSingleTapConfirmed");
			return super.onSingleTapConfirmed(e);
		}
		
		@Override
		public boolean onSingleTapUp(MotionEvent e) {
			Log.i("tag", "onSingleTapUp");
			return super.onSingleTapUp(e);
		}
	};
}

イベント発生順番
実際に実行してみてログを確認すると次々とログが出力されています
device128.png

各タッチイベントごとの発生順番は以下の通りとなっています
・シングルタップ
onDown → onShowPress → onSingleTapUp → onSingleTapConfirmed

・ロングタップ
onDown → onShowPress -> onLongPress

・ダブルタップ
onDown → onSingleTapUp → onDoubleTap → onDoubleTapEvent
 → onDown → onDoubleTapEvent

・スクロール
onDown → onScroll * n

・フリック
onDown → onScroll * n → onFling
スポンサードリンク

posted by kenken at 09:28 | Comment(0) | TrackBack(0) | イベント イベント処理 | このブログの読者になる | 更新情報をチェックする
2012年06月13日

キーを無効にする


イベントからは少し外れますが特定のキーを無効にする方法もあります
無効にしたいキーのイベントが発生したときに
dispatchKeyEventメソッドにおいてtrueを返せば無効にすることができます
dispatchKeyEventは
キーを押したとき・押し続けたとき・キーを離したときに呼び出されます
つまり呼び出されたときにif文で特定のイベント時と
特定のキーが押されたときだけtureを出力すれば無効にすることができます

今回はサンプルプログラムとしてbackキーを無効にしたいと思います
実際にはあまり使うこともありませんが
誤動作で終了させるのを防ぐための処置等に使う・・・かもしれませんw
MainActivity.java
package blog.test;
 

import android.app.Activity;
import android.os.Bundle;
import android.view.KeyEvent;

public class MainActivity extends Activity {
/** Called when the activity is first created. */
@Override
	public void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.main);
}
	
	// dispatchKeyEventを設定
	@Override
	public boolean dispatchKeyEvent(KeyEvent event) {
		//ボタンが押された時を指定
		if(event.getAction() == KeyEvent.ACTION_DOWN) {
			// BACKキーを指定
			if(event.getKeyCode() == KeyEvent.KEYCODE_BACK) {// BACKキー
		return true;
			}
		}
		return super.dispatchKeyEvent(event);
	}
}

これで実行するとbackキーが無効になったためアプリが終了できなくなりましたww Homeキー等で戻ってくださいねw

なおbackキーは他のキーと異なり
キーUP時にdispatchKeyEventメソッドがコールされないようです
またHOMEキーは押してもdispatchKeyEventメソッドがコールされないので
無効化できません
無敵ww
スポンサードリンク

posted by kenken at 15:30 | Comment(0) | TrackBack(0) | イベント イベント処理 | このブログの読者になる | 更新情報をチェックする
2012年06月12日

タッチイベントを取得する


前回はActivityのonTouchEventとonKeyDownを取得しました
実はonTouchEventはタッチパネルを操作時に
ACTION_DOWNACTION_MOVE(繰返し)→ACTION_UPの順に発生しています
今回はこれらをonTouchEventメソッドをオーバーライドして取得してみます
これは以前手書き入力のときにViewクラスで使用したものをActivityクラスに変換したものです
手書き入力を行う(1)
今回も前回と同様にMotionEventのgetX・getYでタッチされたx, y座標を取得しています
それに加えACTION_DOWN・ACTION_MOVE・ACTION_UPをそれぞれログで出力するものにしました
ちなみにlayout/main.xmlには何も配置していません
MainActivity.java
package blog.test;
 

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;

public class MainActivity extends Activity {
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
	//イベントの起きた座標を取得
	float x = event.getX();
	float y = event.getY();
	String action = "";
	
	switch(event.getAction() & MotionEvent.ACTION_MASK) {
	case MotionEvent.ACTION_DOWN:
		action = "Touch Down";
		break;
	case MotionEvent.ACTION_MOVE:
		action = "Touch Move";
		break;
	case MotionEvent.ACTION_UP:
		action = "Touch Up";
		break;
	case MotionEvent.ACTION_CANCEL:
		action = "Touch Cancel";
		break;
	}
	//イベント座標のログ出力
	Log.i("tag", action + " x=" + x + ", y=" + y);
	return super.onTouchEvent(event);
	}
}
MotionEventが何が起こったか場合分けしてactionに文字を入力しています
最後に入力された文字とイベント座標を同時に出力しています

これを実行すると真っ黒な画面が出てきますが
いろんなところをタッチすると次々にログが出力されていきます
device127.png
スポンサードリンク

posted by kenken at 17:03 | Comment(0) | TrackBack(0) | イベント イベント処理 | このブログの読者になる | 更新情報をチェックする