Multitouch Test

Gerade haben wir die App “Multitouch Test” für Android 2.0 in den Market gestellt. Bald wird dazu ein Artikel in einem Print-Magazin erscheinen. Auch Nicht-Entwickler können mit der App rumspielen und die Multi-Touch Fähigkeiten ihres Geräts ausprobieren. Hier gibt es große Unterschiede bei der Android Hardware.

Direktlink zum Androidmarket (funktioniert nur im Androidbrowser)

Der Source-Code veranschaulicht die Multi-Touch Entwicklung und steht Entwicklern frei zur Verfügung. Downloadlink: MultitouchActivity.java.

package de.greenrobot.multitouchtest;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.View.OnTouchListener;

/**
* Demonstrates multitouch capabilities and visualizes MotionEvents.
*
* @author Markus Junginger, greenrobot
*/
public class MultitouchActivity extends Activity implements OnTouchListener {

private static final int MAX_POINTERS = 20;

private TouchView touchView;
private Paint paint;
private Paint paintInfoText;

private PointF[] points;
private int[] lastActions;
private int pointerCount;

private float displayDensity;
private int radius;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
displayDensity = getResources().getDisplayMetrics().density;

points = new PointF[MAX_POINTERS];
lastActions = new int[MAX_POINTERS];

paint = new Paint();
paint.setAntiAlias(true);
paint.setTextSize(calcDevicePixels(15));

paintInfoText = new Paint();
paintInfoText.setColor(Color.BLACK);
paintInfoText.setAntiAlias(true);
paintInfoText.setTextSize(calcDevicePixels(18));

touchView = new TouchView(this);
touchView.setOnTouchListener(this);

requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(touchView);

radius = calcDevicePixels(80);
}

public int calcDevicePixels(int deviceIndependentPixel) {
return (int) (deviceIndependentPixel * displayDensity + 0.5f);
}

@Override
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction() & MotionEvent.ACTION_MASK;
int pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;
pointerCount = event.getPointerCount();

int actionId = event.getPointerId(pointerIndex);
Log.d(“greenrobot”, “MotionEvent – pointer ID: ” + actionId + “, action: ” + mapActionCodeToString(action)
+ “, pointer count: ” + pointerCount);
if (actionId < MAX_POINTERS) {
lastActions[actionId] = action;
}

for (int i = 0; i < pointerCount; i++) {
int pointerId = event.getPointerId(i);
if (pointerId < MAX_POINTERS) {
points[pointerId] = new PointF(event.getX(i), event.getY(i));
if (action == MotionEvent.ACTION_MOVE) {
lastActions[pointerId] = action;
}
}
}

touchView.invalidate();
return true;
}

private class TouchView extends View {

public TouchView(Context context) {
super(context);
setBackgroundColor(Color.WHITE);
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (int i = 0; i < MAX_POINTERS; i++) {
PointF point = points[i];
if (point != null) {
paint.setColor(getColor(i));
canvas.drawCircle(point.x, point.y, radius, paint);
String text = getActionText(i);
float textWidth = paint.measureText(text);
canvas.drawText(text, point.x - textWidth / 2, point.y - radius - calcDevicePixels(8), paint);
}
}
canvas.drawText("Last pointer count: " + pointerCount, 10, calcDevicePixels(30), paintInfoText);
}
}

public int getColor(int pointerId) {
int color;
switch (lastActions[pointerId]) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
color = 0xaa0000ff; // blue
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
color = 0xaa999999; // grey
break;
case MotionEvent.ACTION_MOVE:
color = 0xaa00ff00; // green
break;
default:
color = 0xaaFF0000; // red
}
return color;
}

public String getActionText(int pointerId) {
String action = mapActionCodeToString(lastActions[pointerId]);
return pointerId + ": " + action;
}

private String mapActionCodeToString(int actionCode) {
String action;
switch (actionCode) {
case MotionEvent.ACTION_DOWN:
action = "Down";
break;
case MotionEvent.ACTION_POINTER_DOWN:
action = "Pointer Down";
break;
case MotionEvent.ACTION_UP:
action = "Up";
break;
case MotionEvent.ACTION_POINTER_UP:
action = "Pointer Up";
break;
case MotionEvent.ACTION_MOVE:
action = "Move";
break;
default:
action = "Other (" + actionCode + ")";
}
return action;
}

}