onTouchEvent()メソッド(マルチタッチ)
2011年9月27日(火) 4:23 PM
マルチタッチを使って、タッチしたところに赤色と青色の丸を描画するサンプルを作ってみました。



画面をタッチすると、赤や青の丸が描画される。(イメージ)
タッチしたまま移動すると、丸もそれに合わせて移動する(イメージ)
画面から手を放すと丸が消えてしまう(イメージ)
マルチタッチを使うには、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); } }
Tag:
カスタムViewの実装の仕方
2011年9月26日(月) 3:43 PM
カスタムビューを使って、画面の真ん中に円を描くサンプルをつくってみました。
ボタンやテキストビューなど初めから用意されているViewだけでなく、自分自身でカスタムしたオリジナルViewを実装することができます。カスタムビューはゲームや複雑なアプリをつくるときに使われます。

◆実装の仕方◆
①Viewを継承したCustomViewクラスのための新しいファイル「CustomView.java」を作成する。
「CustomView.java」のソースコード
package com.appliinfo.android.samplethree; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; import android.view.View; public class CustomView extends View { private Context mContext; private Paint mCirclePaint = new Paint(); //コンストラクタ 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); canvas.drawColor(Color.WHITE); //画面のサイズを取得 int width = getWidth(); int height = getHeight(); //ペイントの色とスタイルをセット(色:青色 スタイル:図形の中を塗りつぶす) mCirclePaint.setARGB(255, 153, 204, 255); mCirclePaint.setStyle(Paint.Style.FILL); //画面の中心に円を描く canvas.drawCircle(width / 2, height / 2, 25, mCirclePaint); } }
②res/layout/main.xmlにカスタムViewをセットする。
res/layout/main.xmlのソースコード
<?xml version=”1.0″ encoding=”utf-8″?>
<com.appliinfo.android.samplethree.CustomView xmlns:android=”http://schemas.android.com/apk/res/android“
android:id=”@+id/customview”
android:orientation=”vertical”
android:layout_width=”fill_parent”
android:layout_height=”fill_parent”
android:background=”#FF000000″>
</com.appliinfo.android.samplethree.CustomView>
③LayoutInflaterを使ってmain.xmlからViewを生成し、setContentView()でセットする。
LayoutInflaterを使うと、動的にレイアウトxmlからViewを生成することができるので、プログラム実行中にレイアウトを切り替えることもできるそうです。
「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); } }
残りの設定(AndroidManifest.xml)は、新しいプロジェクトをつくった時のままです。
Tag:
MediaPlayerを使ったサウンドの再生
2011年6月19日(日) 4:08 PM
◆MediaPlayerの特徴:データをストリーム形式で読み込み、破棄する。BGMなどの大きいファイルを再生するときによく使われる。
良い点:メモリの負担が小さい
悪い点:呼び出しから再生までの時間がSoundPoolに比べて遅い
◆MediaPlayerを使って、サウンドを再生するには、以下のようにします。
*サウンド再生
private MediaPlayer mBgm;
this.mBgm = MediaPlayer.create(this, R.raw.bgm_title);
this.mBgm.setLooping(true);
this.mBgm.setVolume(1.0f, 1.0f);
mBgm.seekTo(0);
mBgm.start();
*サウンドの休止
mBgm.pause();
*サウンドの停止と破棄
mBgm.stop();
mBgm.release();
◆MediaPlayerクラスのメソッド
○MediaPlayer.create(Context context, int resid)
第一引数:コンテキスト 第二引数:リソースID
○setLooping(boolean looping)
第一引数:ループするかどうか(true:ループする false:ループしない)
○setVolume(float leftVolume, float rightVolume)
ボリューム設定(0.0~1.0の間で設定する)
○seekTo(int msec)
音楽の開始位置をミリ秒単位で指定する。
◆ブログ記事「SoundPoolを利用したサウンドの再生」のサンプルに、MediaPlayerを利用したサウンドの再生機能を加えてみました。
*変更点
①「res」→「raw」フォルダの中にbgm_title.midファイルを加えました。
②src/com.example.android.sample/Sample.javaの変更
package com.example.android.sampletwo; import android.app.Activity; import android.content.SharedPreferences; import android.media.AudioManager; import android.media.MediaPlayer; import android.media.SoundPool; import android.os.Bundle; import android.view.MotionEvent; import android.view.Window; import android.view.WindowManager; import android.widget.TextView; public class SampleTwo extends Activity { private TextView aTextView; private TextView bTextView; private char[] charactor = new char[4]; private String moji; private int x, y; private SoundPool mSoundPool; private int SoundId; private MediaPlayer mBgm; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.main); aTextView = (TextView) findViewById(R.id.myTextView); bTextView = (TextView) findViewById(R.id.myTextPosition); //データの書き込み SharedPreferences pref = this.getSharedPreferences("MemoPrefs", MODE_PRIVATE); aTextView.setText(pref.getString("memo", "")); bTextView.setText("X:" + pref.getInt("xposition", 0) + " Y:" + pref.getInt("yposition", 0)); //SoundPoolの生成と読み込み this.mSoundPool = new SoundPool(1, AudioManager.STREAM_MUSIC, 0); this.SoundId = mSoundPool.load(this, R.raw.sb_blast, 1); //MediaPlayerの生成と読み込み this.mBgm = MediaPlayer.create(this, R.raw.bgm_title); this.mBgm.setLooping(true); this.mBgm.setVolume(1.0f, 1.0f); mBgm.seekTo(0); mBgm.start(); } @Override public boolean onTouchEvent(MotionEvent event) { x = (int)event.getX(); y = (int)event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: charactor[0] = (char)(68); //D charactor[1] = (char)(79); //O charactor[2] = (char)(87); //W charactor[3] = (char)(78); //N moji = String.valueOf(charactor); aTextView.setText(moji); bTextView.setText("X:" + x + " Y:" + y); break; case MotionEvent.ACTION_UP: charactor[0] = (char)(85); //U charactor[1] = (char)(80); //P charactor[2] = (char)(32); //スペース charactor[3] = (char)(32); //スペース moji = String.valueOf(charactor); aTextView.setText(moji); bTextView.setText("X:" + x + " Y:" + y); mSoundPool.play(SoundId, 1.0f, 1.0f, 1, 0, 1.0f); break; case MotionEvent.ACTION_MOVE: charactor[0] = (char)(77); //M charactor[1] = (char)(79); //O charactor[2] = (char)(86); //V charactor[3] = (char)(69); //E moji = String.valueOf(charactor); aTextView.setText(moji); bTextView.setText("X:" + x + " Y:" + y); break; case MotionEvent.ACTION_CANCEL: aTextView.setText("ACTION_CANCEL"); break; } return super.onTouchEvent(event); } protected void onResume() { super.onResume(); mBgm.start(); } protected void onRestart() { super.onRestart(); mBgm.start(); } protected void onPause() { super.onPause(); mBgm.pause(); } protected void onStop() { super.onStop(); //データの保存 SharedPreferences pref = this.getSharedPreferences("MemoPrefs", MODE_PRIVATE); SharedPreferences.Editor editor = pref.edit(); editor.putString("memo", aTextView.getText().toString()); editor.putInt("xposition", x); editor.putInt("yposition", y); editor.commit(); mBgm.pause(); } protected void onDestroy() { super.onDestroy(); mBgm.stop(); mBgm.release(); } }
Tag:
SoundPoolを利用したサウンドの再生
2011年6月17日(金) 3:05 PM
◆SoundPoolの特徴:データをメモリに保存してから、再生を行うため、サウンドエフェクト(SE)の再生に向いています。
良い点:呼び出しから再生までの時間が短い。
悪い点:メモリの負担が大きい。
◆SoundPoolを使って、サウンドを再生するには、以下のようにします。
private SoundPool mSoundPool;
private int SoundId;
this.mSoundPool = new SoundPool(1, AudioManager.STREAM_MUSIC, 0);
this.SoundId = mSoundPool.load(this, R.raw.sb_blast, 1);
mSoundPool.play(SoundId, 1.0f, 1.0f, 1, 0, 1.0f);
◆SoundPoolクラスのメソッド
○SoundPool(int maxStreams, int streamType, int srcQuality)
第一引数:読み込むファイルの数
○load(Context context, int resId, int priority)
第一引数:コンテキスト 第二引数:リソースID
○play(int soundID, float leftVolume, float rightVolume, int priority, int loop, float rate)
第五引数:ループ回数(0:ループしない -1:無限ループ)
◆ブログ記事「SharedPreferencesを使ったデータの保存と書き込み」のサンプルに、SoundPoolを利用したサウンドの再生機能を加えてみました。
*変更点
①「res」フォルダに「raw」フォルダ作成し、sb_blast.oggファイルを加えました。
②src/com.example.android.sample/Sample.javaの変更
package com.example.android.sampletwo; import android.app.Activity; import android.content.SharedPreferences; import android.media.AudioManager; import android.media.SoundPool; import android.os.Bundle; import android.view.MotionEvent; import android.view.Window; import android.view.WindowManager; import android.widget.TextView; public class SampleTwo extends Activity { private TextView aTextView; private TextView bTextView; private char[] charactor = new char[4]; private String moji; private int x, y; private SoundPool mSoundPool; private int SoundId; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.main); aTextView = (TextView) findViewById(R.id.myTextView); bTextView = (TextView) findViewById(R.id.myTextPosition); //データの書き込み SharedPreferences pref = this.getSharedPreferences("MemoPrefs", MODE_PRIVATE); aTextView.setText(pref.getString("memo", "")); bTextView.setText("X:" + pref.getInt("xposition", 0) + " Y:" + pref.getInt("yposition", 0)); //SoundPoolの生成と読み込み this.mSoundPool = new SoundPool(1, AudioManager.STREAM_MUSIC, 0); this.SoundId = mSoundPool.load(this, R.raw.sb_blast, 1); } @Override public boolean onTouchEvent(MotionEvent event) { x = (int)event.getX(); y = (int)event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: charactor[0] = (char)(68); //D charactor[1] = (char)(79); //O charactor[2] = (char)(87); //W charactor[3] = (char)(78); //N moji = String.valueOf(charactor); aTextView.setText(moji); bTextView.setText("X:" + x + " Y:" + y); break; case MotionEvent.ACTION_UP: charactor[0] = (char)(85); //U charactor[1] = (char)(80); //P charactor[2] = (char)(32); //スペース charactor[3] = (char)(32); //スペース moji = String.valueOf(charactor); aTextView.setText(moji); bTextView.setText("X:" + x + " Y:" + y); mSoundPool.play(SoundId, 1.0f, 1.0f, 1, 0, 1.0f); break; case MotionEvent.ACTION_MOVE: charactor[0] = (char)(77); //M charactor[1] = (char)(79); //O charactor[2] = (char)(86); //V charactor[3] = (char)(69); //E moji = String.valueOf(charactor); aTextView.setText(moji); bTextView.setText("X:" + x + " Y:" + y); break; case MotionEvent.ACTION_CANCEL: aTextView.setText("ACTION_CANCEL"); break; } return super.onTouchEvent(event); } protected void onStop() { super.onStop(); //データの保存 SharedPreferences pref = this.getSharedPreferences("MemoPrefs", MODE_PRIVATE); SharedPreferences.Editor editor = pref.edit(); editor.putString("memo", aTextView.getText().toString()); editor.putInt("xposition", x); editor.putInt("yposition", y); editor.commit(); } }
Tag:
SharedPreferencesを使ったデータの保存と書き込み
2011年6月15日(水) 2:22 PM
SharedPreferencesを使うと、データの保存と書き込みが簡単にできます。
*データの書き込み
aTextView = (TextView) findViewById(R.id.myTextView);
SharedPreferences pref = this.getSharedPreferences(“MemoPrefs”, MODE_PRIVATE);
aTextView.setText(pref.getString(“memo”, “”));
説明:
“MemoPrefs”という名前のxmlファイルを呼び出して、その中にある、”memo”という名前が付けられたデータをaTextViewにセットしています。また、データの書き込みはonCreateメソッドの中で処理を行うのが一般的みたいです。
*データの保存
aTextView = (TextView) findViewById(R.id.myTextView);
int x = 10;
SharedPreferences pref = this.getSharedPreferences(“MemoPrefs”, MODE_PRIVATE);
SharedPreferences.Editor editor = pref.edit();
editor.putString(“memo”, aTextView.getText().toString());
editor.putInt(“xposition”, x);
editor.commit();
説明:
“MemoPrefs”という名前のxmlファイルを呼び出して、pref.edit();でxmlファイルを編集できるようにします。次に、”memo”という名前のデータにテキストビューの文字列を代入し、”xposition”のデータにxの値を代入しています。最後に、editor.commit();して、実行しています。また、データの書き込みはonStopメソッドの中で処理を行うのが一般的みたいです。
◆SharedPreferencesで保存したデータは、
アプリを実行した状態で、「Eclipse」の「DDMS」→「ファイル・エクスプローラー」タブを選択する。
フォルダ「data」→「data」→「パッケージ名」→「shared_prefs」→「MemoPrefs.xml」に保存されています。
中身を見る場合は、MemoPrefs.xmlを選択し、「ファイル・エクスプローラー」タブの横にあるアイコン(マウスを乗せるとPull a file from the deviceと表示される)をクリックし、任意の場所にエクスポートします。◆
ブログ記事「タッチパネルの位置情報を調べる」のサンプルに、SharedPreferencesを使ったデータの保存と書き込み機能を加えてみました。
*src/com.example.android.sample/Sample.javaの変更後の全ソース:
package com.example.android.sampletwo; import android.app.Activity; import android.content.SharedPreferences; import android.os.Bundle; import android.util.Log; import android.view.MotionEvent; import android.view.Window; import android.view.WindowManager; import android.widget.TextView; public class SampleTwo extends Activity { private TextView aTextView; private TextView bTextView; private char[] charactor = new char[4]; private String moji; private int x, y; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.main); aTextView = (TextView) findViewById(R.id.myTextView); bTextView = (TextView) findViewById(R.id.myTextPosition); //データの書き込み SharedPreferences pref = this.getSharedPreferences("MemoPrefs", MODE_PRIVATE); aTextView.setText(pref.getString("memo", "")); bTextView.setText("X:" + pref.getInt("xposition", 0) + " Y:" + pref.getInt("yposition", 0)); } @Override public boolean onTouchEvent(MotionEvent event) { x = (int)event.getX(); y = (int)event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: charactor[0] = (char)(68); //D charactor[1] = (char)(79); //O charactor[2] = (char)(87); //W charactor[3] = (char)(78); //N moji = String.valueOf(charactor); aTextView.setText(moji); bTextView.setText("X:" + x + " Y:" + y); break; case MotionEvent.ACTION_UP: charactor[0] = (char)(85); //U charactor[1] = (char)(80); //P charactor[2] = (char)(32); //スペース charactor[3] = (char)(32); //スペース moji = String.valueOf(charactor); aTextView.setText(moji); bTextView.setText("X:" + x + " Y:" + y); break; case MotionEvent.ACTION_MOVE: charactor[0] = (char)(77); //M charactor[1] = (char)(79); //O charactor[2] = (char)(86); //V charactor[3] = (char)(69); //E moji = String.valueOf(charactor); aTextView.setText(moji); bTextView.setText("X:" + x + " Y:" + y); break; case MotionEvent.ACTION_CANCEL: aTextView.setText("ACTION_CANCEL"); break; } return super.onTouchEvent(event); } protected void onStop() { super.onStop(); //データの保存 SharedPreferences pref = this.getSharedPreferences("MemoPrefs", MODE_PRIVATE); SharedPreferences.Editor editor = pref.edit(); editor.putString("memo", aTextView.getText().toString()); editor.putInt("xposition", x); editor.putInt("yposition", y); editor.commit(); }
}
Tag: