Monday, November 11, 2013

Multi Touch Events in Android Programming

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.

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>