This is a short article to describe what actions, indexes, and identifiers MotionEvent class in Android hasin several scenarios using single and multi touch events. This will complement the contents of Google's tutorials such as
- http://developer.android.com/training/gestures/multi.html#track
- http://android-developers.blogspot.kr/2010/06/making-sense-of-multitouch.html
where the existing tutorials are very helpful, but they are still not so clear at least to me. This is the reason why I post this article showing concrete values of MotionEvent objects received for touch events in the scenarios that follows.
0. Scenarios of Interest
- [Single Touch Scenario 1] Finger A touches down, moves and is up.
- [Multi Touch Scenario 1] Finger A touches down, finger B touches down, A is up, and B is up.
- [Multi Touch Scenario 2] Finger A touches down, finger B touches down, B is up, and A is up.
- [Multi Touch Scenario 3] Finger A touches down, finger B touches down, A moves, A is up, and B is up.
- [Multi Touch Scenario 4] Finger A touches down, finger B touches down, A moves, B is up, and A is up.
- [Multi Touch Scenario 5] Finger A touches down, finger B touches down, B moves, B is up, and A is up.
- [Multi Touch Scenario 6] Finger A touches down, finger B touches down, B moves, A is up, and B is up.
1. Multi Touches and their Values in MotionEvent
[Single Touch Scenario 1] Finger A touches down, moves and is up.
[Multi Touch Scenario 5] Finger A touches down, finger B touches down, B moves, B is up, and A is up.
INDEX0 : Down
INDEX0 - ID0 : 182, 370
INDEX1 : Pointer Down
INDEX0 - ID0 : 182, 370
INDEX1 - ID1 : 361, 412
INDEX0 : Move
INDEX0 - ID0 : 182, 370
INDEX1 - ID1 : 361, 415
INDEX0 : Move
INDEX0 - ID0 : 182, 370
INDEX1 - ID1 : 361, 420
INDEX1 : Pointer Up
INDEX0 - ID0 : 182, 370
INDEX1 - ID1 : 361, 420
INDEX0 : Up
INDEX0 - ID0 : 182, 370
[Multi Touch Scenario 6] Finger A touches down, finger B touches down, B moves, A is up, and B is up.
INDEX0 : Down
INDEX0 : ID0 : 120, 335
INDEX1 : Pointer Down
INDEX0 : ID0 : 120, 335
INDEX1 : ID1 : 351, 339
INDEX0 : Move
INDEX0 : ID0 : 120, 335
INDEX1 : ID1 : 351, 341
INDEX0 : Poiner Up
INDEX0 : ID0 : 120, 335
INDEX1 : ID1 : 351, 341
INDEX0 : Up
INDEX0 : ID1 : 351, 341
Note that, interestingly, whichever fingers move, the index of moving finger is always zero.
2. Android Program for Multi Touch Testing
The Android program for this testing receives touch events to print logs to the TextView in the activity screen.
package com.example.multitouchtest;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity {
TextView text;
Button button;
String info;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text = (TextView)findViewById(R.id.textview);
button = (Button)findViewById(R.id.button1);
info = "";
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
info = "";
text.setText(info);
}
});
}
@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) {
int action = event.getActionMasked();
int index = event.getActionIndex();
String actionString = "";
switch(action) {
case MotionEvent.ACTION_DOWN:
actionString = "Down";
break;
case MotionEvent.ACTION_MOVE:
actionString = "Move";
break;
case MotionEvent.ACTION_POINTER_DOWN:
actionString = "Pointer Down";
break;
case MotionEvent.ACTION_UP:
actionString = "Up";
break;
case MotionEvent.ACTION_POINTER_UP:
actionString = "Pointer Up";
break;
}
info = info + "INDEX" + index + " : " + actionString + "\n";
for (int i=0; i<event.getPointerCount(); i++) {
info = info +
"INDEX" + i + " - " +
"ID" + event.getPointerId(i) +
" : " + (int)event.getX(i) + ", " + (int)event.getY(i) + "\n";
}
// info = info + event.toString();
text.setText(info);
return true;
}
}
- http://developer.android.com/training/gestures/multi.html#track
- http://android-developers.blogspot.kr/2010/06/making-sense-of-multitouch.html
where the existing tutorials are very helpful, but they are still not so clear at least to me. This is the reason why I post this article showing concrete values of MotionEvent objects received for touch events in the scenarios that follows.
0. Scenarios of Interest
- [Single Touch Scenario 1] Finger A touches down, moves and is up.
- [Multi Touch Scenario 1] Finger A touches down, finger B touches down, A is up, and B is up.
- [Multi Touch Scenario 2] Finger A touches down, finger B touches down, B is up, and A is up.
- [Multi Touch Scenario 3] Finger A touches down, finger B touches down, A moves, A is up, and B is up.
- [Multi Touch Scenario 4] Finger A touches down, finger B touches down, A moves, B is up, and A is up.
- [Multi Touch Scenario 5] Finger A touches down, finger B touches down, B moves, B is up, and A is up.
- [Multi Touch Scenario 6] Finger A touches down, finger B touches down, B moves, A is up, and B is up.
1. Multi Touches and their Values in MotionEvent
[Single Touch Scenario 1] Finger A touches down, moves and is up.
INDEX0 : Down
INDEX0 - ID0 : 412, 447
INDEX0 : Move
INDEX0 - ID0 : 412, 449
INDEX0 : Move
INDEX0 - ID0 : 412, 451
INDEX0 : Move
INDEX0 - ID0 : 412, 453
INDEX0 : Up
INDEX0 - ID0 : 412, 453
[Multi Touch Scenario 1] Finger A touches down, finger B touches down, A is up, and B is up.
INDEX0 : Down
INDEX0 : ID0 : 161, 547
INDEX1 : Pointer Down
INDEX0 - ID0 : 161, 547
INDEX1 - ID1 : 370, 355
INDEX0 : Pointer Up
INDEX0 - ID0 : 161, 547
INDEX1 - ID1 : 370, 355
INDEX0 : Up
INDEX0 - ID1 : 370, 355
[Multi Touch Scenario 2] Finger A touches down, finger B touches down, B is up, and A is up.
INDEX0 : Down
INDEX0 - ID0 : 130, 541
INDEX1 : Pointer Down
INDEX0 - ID0 : 130, 541
INDEX1 - ID1 : 354, 338
INDEX1 : Pointer Up
INDEX0 - ID0 : 130, 541
INDEX1 - ID1 : 354, 338
INDEX0 : Up
INDEX0 - ID0 : 130, 541
[Multi Touch Scenario 3] Finger A touches down, finger B touches down, A moves, A is up, and B is up.
INDEX0 : Down
INDEX0 - ID0 : 149, 505
INDEX1 : Pointer Down
INDEX0 - ID0 : 149, 505
INDEX1 - ID1 : 365, 327
INDEX0 : Move
INDEX0 - ID0 : 149, 506
INDEX1 - ID1 : 365, 327
INDEX0 : Move
INDEX0 - ID0 : 151, 508
INDEX1 - ID1 : 365, 327
INDEX0 : Pointer Up
INDEX0 - ID0 : 151, 508
INDEX1 - ID1 : 365, 327
INDEX0 : Up
INDEX0 - ID1 : 365, 327
[Multi Touch Scenario 4] Finger A touches down, finger B touches down, A moves, B is up, and A is up.
INDEX0 : Down
INDEX0 - ID0 : 125, 365
INDEX1 : Pointer Down
INDEX0 - ID0 : 125, 365
INDEX1 - ID1 : 342, 373
INDEX0 : Move
INDEX0 - ID0 : 125, 366
INDEX1 - ID1 : 342, 373
INDEX0 : Move
INDEX0 - ID0 : 128, 371
INDEX1 - ID1 : 342, 373
INDEX1 : Pointer Up
INDEX0 - ID0 : 128, 371
INDEX1 - ID1 : 342, 373
INDEX0 : Up
INDEX0 - ID0 : 128, 371
[Multi Touch Scenario 5] Finger A touches down, finger B touches down, B moves, B is up, and A is up.
INDEX0 : Down
INDEX0 - ID0 : 182, 370
INDEX1 : Pointer Down
INDEX0 - ID0 : 182, 370
INDEX1 - ID1 : 361, 412
INDEX0 : Move
INDEX0 - ID0 : 182, 370
INDEX1 - ID1 : 361, 415
INDEX0 : Move
INDEX0 - ID0 : 182, 370
INDEX1 - ID1 : 361, 420
INDEX1 : Pointer Up
INDEX0 - ID0 : 182, 370
INDEX1 - ID1 : 361, 420
INDEX0 : Up
INDEX0 - ID0 : 182, 370
[Multi Touch Scenario 6] Finger A touches down, finger B touches down, B moves, A is up, and B is up.
INDEX0 : Down
INDEX0 : ID0 : 120, 335
INDEX1 : Pointer Down
INDEX0 : ID0 : 120, 335
INDEX1 : ID1 : 351, 339
INDEX0 : Move
INDEX0 : ID0 : 120, 335
INDEX1 : ID1 : 351, 341
INDEX0 : Poiner Up
INDEX0 : ID0 : 120, 335
INDEX1 : ID1 : 351, 341
INDEX0 : Up
INDEX0 : ID1 : 351, 341
Note that, interestingly, whichever fingers move, the index of moving finger is always zero.
2. Android Program for Multi Touch Testing
The Android program for this testing receives touch events to print logs to the TextView in the activity screen.
package com.example.multitouchtest;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity {
TextView text;
Button button;
String info;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text = (TextView)findViewById(R.id.textview);
button = (Button)findViewById(R.id.button1);
info = "";
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
info = "";
text.setText(info);
}
});
}
@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) {
int action = event.getActionMasked();
int index = event.getActionIndex();
String actionString = "";
switch(action) {
case MotionEvent.ACTION_DOWN:
actionString = "Down";
break;
case MotionEvent.ACTION_MOVE:
actionString = "Move";
break;
case MotionEvent.ACTION_POINTER_DOWN:
actionString = "Pointer Down";
break;
case MotionEvent.ACTION_UP:
actionString = "Up";
break;
case MotionEvent.ACTION_POINTER_UP:
actionString = "Pointer Up";
break;
}
info = info + "INDEX" + index + " : " + actionString + "\n";
for (int i=0; i<event.getPointerCount(); i++) {
info = info +
"INDEX" + i + " - " +
"ID" + event.getPointerId(i) +
" : " + (int)event.getX(i) + ", " + (int)event.getY(i) + "\n";
}
// info = info + event.toString();
text.setText(info);
return true;
}
}
The Activity layout contains a TextView and a Button (for clear the text in the TextView).
<RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<TextView
android:id="@+id/textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="18dp"
android:text="@string/hello_world" />
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignTop="@+id/textview"
android:layout_marginRight="28dp"
android:text="Clear" />
</RelativeLayout>