素人プログラマ奮闘記

javaの初心者がAndroidのことを独学で勉強しつつ、メモを残していきます。

画面タッチイベントの基本(1)

今回は画面をタッチしたときに何かしらのアクションをするために、タッチされたことを検知して 画面上にタッチされた場所の座標を表示してみたいと思います。

プロジェクト作成

では、プロジェクトの作成からしていきます。
プロジェクト名:ActivityTouchTest
アクテビティ名:MainActivity
レイアウト名 :main

レイアウト作成(main.xml編集)

次はmain/xmlを編集して画面レイアウトを完成させます。
画面下部にTetViewを配置するだけです。

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">
    <LinearLayout
    	android:layout_width="match_parent"
    	android:layout_height="fill_parent"
    	android:orientation="horizontal" >
    	<TextView android:id="@+id/touch_info_text"
    		android:layout_width="fill_parent"
    		android:layout_height="wrap_content"
    		android:layout_gravity="bottom"
    		android:text="" />
    </LinearLayout>
</LinearLayout>

メイン処理作成(Activity.java 編集)

次にMainActivityを編集していきます。
タッチイベントを取得するには、ActivityクラスのonTouchEvent()をオーバーライドします。
引数には、MotionEventのインスタンスが渡されます。

package com.example.activitytouchtest;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
 import android.view.MotionEvent;

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}
	
	@Override	
	public boolean onTouchEvent(MotionEvent event) {
		// TODO 自動生成されたメソッド・スタブ
		return super.onTouchEvent(event);
	}

}

画面がタッチされた場合、このonTouchEventイベントが発生します。
第一引数にMotionEventクラスが渡されるので、これを使って現在位置などの情報を取得します。

●よく使うメソッド一覧

float x = event.getX(); //タッチしたX座標
float y = event.getY(); //タッチしたY座標
float size = event.getSize(); //押された画面領域サイズ
float press = event.getPressure(); //画面が押された際の圧力
int count = event.getPointerCount(); //画面タッチ数の取得
long downTime = event.getDownTime(); //押されていた時間(ms単位)の取得
int actionID = event.getAction(); //タッチイベントのアクション種別ID

●event.getAction()で取得した動作ID(定数リスト)
MotionEvent.ACTION_DOWN
//タッチパネルがまだタッチされていない状態で タッチ押下

MotionEvent.ACTION_MOVE
//タッチパネルを押したままスライドさせた場合

MotionEvent.ACTION_UP
//タッチパネルが押された状態で、タッチパネルから指を持ち上げた場合

MotionEvent.ACTION_CANCEL 
//タッチパネルをタッチするのがキャンセルされた

MotionEvent.ACTION_POINTER_UP 
//タッチパネルが1カ所以上タッチタッチされている状態で、新たにタッチ押下(複数タッチ)

MotionEvent.ACTION_POINTER_DOWN 
//タッチパネルが1カ所以上タッチタッチされている状態で、タッチパネルから指を持ち上げた場合(複数タッチ解除)

MotionEvent.ACTION_OUTSIDE 
//ターゲット外の範囲をタッチ

上記を踏まえて全体のソースです。

package com.example.activitytouchtest;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.MotionEvent;
import android.widget.TextView;

public class MainActivity extends Activity {

	private TextView touchInfoText = null;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		//タッチ情報表示テキスト		
		this.touchInfoText = (TextView)findViewById(R.id.touch_info_text);
		
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}
	
	@Override	
	public boolean onTouchEvent(MotionEvent event) {
		// TODO 自動生成されたメソッド・スタブ

		float x = event.getX();				 	//タッチしたX座標
		float y = event.getY(); 			 	//タッチしたY座標
		float size = event.getSize();		 	//押された画面領域サイズ
		float press = event.getPressure();   	//画面が押された際の圧力
		int count = event.getPointerCount(); 	//画面タッチ数の取得
		long downTime = event.getDownTime(); 	//押されていた時間(ms単位)の取得
		int actionID = event.getAction();		//タッチイベントのアクション種別
		
		String actionKind = "";
		switch (actionID) {
			case MotionEvent.ACTION_DOWN:
				//タッチされた
				actionKind += "ACTION_DOWN";
				break;
			case MotionEvent.ACTION_UP:
				//タッチが離れた
				actionKind += "ACTION_UP";
				break;
			case MotionEvent.ACTION_MOVE:
				//タッチしたまま動いた
				actionKind += "ACTION_MOVE";
				break;
			case MotionEvent.ACTION_CANCEL:
				//タッチがキャンセルされた
				actionKind += "ACTION_CANCEL";
			    break;
			default :
				//ほかの操作
				actionKind += "default";	        	
				break;
		}
		
		String message = String.format(
				"x=%s y=%s size=%s press=%s count=%s downTime=%s action=%s"
				,String.valueOf(x)
				,String.valueOf(y)
				,String.valueOf(size)
				,String.valueOf(press)
				,String.valueOf(count)
				,String.valueOf(downTime)
				,actionKind);
		
		//画面に表示
		this.touchInfoText.setText(message);
		
		return super.onTouchEvent(event);
	}

}

後は実機を使ってデバッグしてください。画面をタッチまたは、タッチスライドするたびに、下部のテキストに 情報が表示されます。


onTouchEventメソッドの返り値について

タッチして、そのまま画面をすべらしてからタッチを離す動作時のイベント順番ですが
DOWN→MOVE→UPになると予想できますよね。

実際開発していた時に、onTouchEventの処理で、DOWNイベントは検出するのに、
それ以後のMOVEイベントやUPイベントを検出しなくて困った時がありました。

色々調べた結果、解決したのでメモに残しておきます。

結論からすると、返り値として「super.onTouchEvent(event) = false」を返していたのがダメだったみたい。

戻り値にfalseを返すとDOWN処理が完了扱いにならないため処理が終了してしまってたみたいです。
自動生成でonTouchEventをオーバーライドするとデフォルトで戻り値が
return super.onTouchEvent(event);になるので
ちゃんと順番に処理してほしいと時はtrueを返すようにしましょう。

カテゴリーへ

inserted by FC2 system