ボタンを同時に押せてしまうと処理が複雑になりとても不便です。そこで、同時に2つ以上のボタンを押しても初めに押されたボタンの処理だけを実行する方法を紹介します。
初めにタッチした指を検出する
ViewGroup(LinearLayout, FrameLayoutなど)にはsplitMotionEventsという属性があります。この属性にfalseを指定することで、そのViewGroup内のボタンのMotionEventを一括で検出できます。
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:splitMotionEvents="false">
<Button android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
public void onCreate(Bundle savedInstanceState) {
~ 省略 ~
Button button1 = (Button)findViewById(R.id.button1);
button1.setOnTouchListener(this);
Button button2 = (Button)findViewById(R.id.button2);
button2.setOnTouchListener(this);
}
public boolean onTouch(View view, MotionEvent event) {
int touchedAction = event.getAction();
Log.d("MainActivity", touchedAction);
}
このようにsplitMotionEventsにfalseを指定することで、LinearLayout内のボタンという範囲でMotionEventを検出することができます。そのため、LinearLayout内のボタンに1本目の指が触れた場合はMotionEventのACTION_DOWN、さらに1本目を触れたまま2本目を触れるとACTION_POINTER_DOWNがtouchedActionに入ります。
補足
splitMotionEventがtrueの場合(デフォルト)はボタンごとにMotionEventが検出されるため、button1とbutton2を同時に押してもそれぞれのtouchedActionにはACTION_DOWNが入ります。
初めに押された指の番号を取得する
初めの指か他の指かは検出できるようになりました。次に初めの指が離されたら処理を実行するため、初めの指の番号を覚えておく必要があります。
private static final int INVALID_POINTER_ID = -1;
private static int mActivePointerId = INVALID_POINTER_ID;
public boolean onTouch(View view, MotionEvent event) {
int touchedAction = event.getAction();
if (touchedAction == MotionEvent.ACTION_DOWN) {
mActivePointerId = me.getPointerId(0);
}
}
今回は初めにタッチされた時に指の番号を覚える必要があるので、ACTION_DOWNの中で今タッチされている初めの指の番号を取得して覚えておきます。0は一番初めに触れたタッチになります。
初めにタッチされたボタンだけ処理を実行する
最後に初めにタッチされたボタンが離された時に処理を実行します。初めにタッチされた指の番号は覚えておいたので、指を離した時に覚えておいた指の番号かどうかで処理を実行します。
private static final int INVALID_POINTER_ID = -1;
private static int mActivePointerId = INVALID_POINTER_ID;
public boolean onTouch(View view, MotionEvent event) {
int touchedAction = event.getAction();
if ( touchedAction== MotionEvent.ACTION_DOWN) {
mActivePointerId = me.getPointerId(0);
} else if (( touchedAction == MotionEvent.ACTION_UP) ||
( touchedAction == MotionEvent.ACTION_POINTER_UP)) {
int pointerIndex = (touchedAction & MotionEvent.ACTION_POINTER_INDEX_MASK)
>> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
if (mActivePointerId == me.getPointerId(pointerIndex)) {
mActivePointerId = INVALID_POINTER_ID;
onClick();
return true;
}
}
return false;
}
離された指の番号は、離された指のindexを取得してそこから求ることができます。ここでは説明を避けます。そして、同じだった場合に処理(onClick)を実行しています。こうすれば複数の指で同時に押されても、初めにタッチされたボタンに関連した処理だけを実行することができます。
補足
指が離された場合は、 touchedActionにACTION_UP(他に指が触れていない場合)、またはACTION_POINTER_UP(他にも指が触れている場合)が入ります。