The Multi TouchHandler

For multitouch handling, we have a class called MultiTouchHandler, as shown in Listing 5-10.

Listing 5-10. (More of the Same) package com.badlogic.androidgames.framework.impl;

import java.util.ArrayList; import java.util.List;

import android.view.MotionEvent; import android.view.View;

import com.badlogic.androidgames.framework.Input.TouchEvent;

import com.badlogic.androidgames.framework.Pool;

import com.badlogic.androidgames.framework.Pool.PoolObjectFactory;

public class MultiTouchHandler implements TouchHandler { boolean[] isTouched = new boolean[20]; int[] touchX = new int[20]; int[] touchY = new int[20]; Pool<TouchEvent> touchEventPool;

List<TouchEvent> touchEvents = new ArrayList<TouchEvent>(); List<TouchEvent> touchEventsBuffer = new ArrayList<TouchEvent>(); float scaleX; float scaleY;

We again let the class implement the TouchHandler interface and have a couple of members to store the current state and events. Instead of storing the state for a single pointer, we simply store the state of 20 pointers. We also have those mysterious scaleX and scaleY members again.

public MultiTouchHandler(View view, float scaleX, float scaleY) {

PoolObjectFactory<TouchEvent> factory = new PoolObjectFactory<TouchEvent>() { ^Override public TouchEvent createObject() { return new TouchEvent();

touchEventPool = new Pool<TouchEvent>(factory, 100); view.setOnTouchListener(this);

this.scaleX = scaleX; this.scaleY = scaleY;

The constructor is exactly the same as the constructor of the SingleTouchHandler: we create a Pool for TouchEvent instances register the handler as an OnTouchListener, and store the scaling values.

^Override public boolean onTouch(View v, MotionEvent event) { synchronized (this) {

int action = event.getAction() & MotionEvent.ACTION_MASK; int pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent. ACTION_POINTER_ID_SHIFT;

int pointerId = event.getPointerId(pointerIndex); TouchEvent touchEvent;

switch (action) {

case MotionEvent.ACTION_DOWN:

case MotionEvent. ACTION_POINTER_DOWN:

touchEvent = touchEventPool.newObject(); touchEvent.type = TouchEvent.TOUCH_DOWN; touchEvent.pointer = pointerId; touchEvent.x = touchX[pointerId] = (int) (event

.getX(pointerIndex) * scaleX); touchEvent.y = touchY[pointerId] = (int) (event

.getY(pointerIndex) * scaleY); isTouched[pointerId] = true; touchEventsBuffer.add(touchEvent); break;

case MotionEvent.ACTION_UP:

case MotionEvent. ACTION_POINTER_UP:

case MotionEvent. ACTION_CANCEL:

touchEvent = touchEventPool.newObject();

touchEvent.type = TouchEvent.TOUCHJJP;

touchEvent.pointer = pointerId;

touchEvent.x = touchX[pointerId] = (int) (event

.getX(pointerIndex) * scaleX); touchEvent.y = touchY[pointerId] = (int) (event

.getY(pointerIndex) * scaleY); isTouched[pointerId] = false; touchEventsBuffer.add(touchEvent); break;

case MotionEvent. ACTION_MOVE:

int pointerCount = event.getPointerCount(); for (int i = 0; i < pointerCount; i++) { pointerIndex = i;

pointerId = event.getPointerId(pointerIndex);

touchEvent = touchEventPool.newObject(); touchEvent.type = TouchEvent.TOJCH_DRAGGED; touchEvent.pointer = pointerId; touchEvent.x = touchX[pointerId] = (int) (event

.getX(pointerIndex) * scaleX); touchEvent.y = touchY[pointerId] = (int) (event

.getY(pointerIndex) * scaleY); touchEventsBuffer.add(touchEvent);


return true;

The onTouch() method looks as intimidating as in our test example in the last chapter. All we do is marry that test code with our event pooling and synchronization here (things we've already talked about in detail). The only real difference to the SingleTouchHandler.onTouch() method is that we handle multiple pointers and set the TouchEvent.pointer member accordingly (instead of just to zero).

@Override public boolean isTouchDown(int pointer) { synchronized (this) {

if (pointer < 0 || pointer >= 20) return false;

else return isTouched[pointer];

@Override public int getTouchX(int pointer) { synchronized (this) {

else return touchX[pointer];

@Override public int getTouchY(int pointer) { synchronized (this) {

else return touchY[pointer];

The polling methods isTouchDown(), getTouchX(), and getTouchY() should look familiar as well. We perform some error checking and then fetch the corresponding pointer state from one of the member arrays that we fill in the onTouch() method.

@Override public List<TouchEvent> getTouchEvents() { synchronized (this) {

int len = touchEvents.size(); for (int i = 0; i < len; i++); touchEvents.clear(); touchEvents.addAll(touchEventsBuffer); touchEventsBuffer.clear(); return touchEvents;

The final method, getTouchEvents(), is again exactly the same as the corresponding method of SingleTouchHandler.getTouchEvents().

Equipped with all those handlers, we can now implement the Input interface.

0 0

Post a comment