The Single TouchHandler Class

In the case of our single-touch handler, we'll ignore any IDs other than zero. As a refresher, let's recall the TouchEvent class defined in Chapter 3 as part of the Input interface:

public static class TouchEvent {

public static final int TOUCH_DOWN = 0; public static final int TOUCH_UP = 1; public static final int TOUCH_DRAGGED = 2;

public int type; public int x, y; public int pointer;

Like the KeyEvent class, it defines a couple of constants encoding the touch event's type, along with the x- and y-coordinates in the coordinate system of the View and the pointer ID.

Listing 5-9 shows the implementation of the TouchHandler interface for Android 1.5 and 1.6.

Listing 5-9. SingleTouchHandler.java; Good with Single Touch, Not So Good with Multitouch 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.Pool;

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

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

public class SingleTouchHandler implements TouchHandler { boolean isTouched; int touchX; int touchY;

Pool<TouchEvent> touchEventPool;

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

We start off by letting the class implement the TouchHandler interface, which also means that we have to implement the OnTouchListener interface. Next are a couple of members that should look familiar. We have three members storing the current state of the touchscreen for one finger, followed by a Pool and two lists holding TouchEvents. This is exactly the same thing we had in the KeyboardHandler. We also have two members, scaleX and scaleY. We'll talk about those in a minute. We'll use these to cope with different screen resolutions.

NOTE: Of course, we could have made that more elegant by letting the KeyboardHandler and SingleTouchHandler derive from a base class that handles all this pooling and synchronization stuff. It would have complicated the explanation even more, though, so instead we'll just write a few more lines of code.

public SingleTouchHandler(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;

In the constructor we register the handler as an OnTouchListener and set up the Pool we use to recycle TouchEvents. We also store the scaleX and scaleY parameters that are passed to the constructor (and ignore them for now).

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

TouchEvent touchEvent = touchEventPool.newObject(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN:

touchEvent.type = TouchEvent.TOUCH_DOWN;

isTouched = true;

break;

case MotionEvent. ACTION_MOVE:

touchEvent.type = TouchEvent.TOUCH_DRAGGED;

isTouched = true;

break;

case MotionEvent. ACTION_CANCEL: case MotionEvent. ACTION_UP:

touchEvent.type = TouchEvent.TOUCH_UP;

isTouched = false;

break;

touchEvent.x = touchX = (int)(event.getX() * scaleX); touchEvent.y = touchY = (int)(event.getY() * scaleY); touchEventsBuffer.add(touchEvent);

return true;

The onTouch() method does the same thing as the onKey() method of our KeyboardHandler, the only difference being that we now handle TouchEvents, not KeyEvents. All the synchronization, pooling, and MotionEvent handling are already known to us. The only interesting thing is that we actually multiply the reported x- and y-coordinates of a touch event by scaleX and scaleY. Remember this, as we'll take a look at it again later on.

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

return isTouched;

else return false;

@Override public int getTouchX(int pointer) { synchronized(this) { return touchX;

@Override public int getTouchY(int pointer) { synchronized(this) { return touchY;

The methods isTouchDown(), getTouchX(), and getTouchY() allow us to poll the touchscreen state based on the members that we set in the onTouch() method. The only noticeable thing about them is that they'll only return useful data for a pointer ID with a value zero, as we only support single-touch screens with this class.

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

int len = touchEvents.size(); for( int i = 0; i < len; i++ )

touchEventPool.free(touchEvents.get(i)); touchEvents.clear(); touchEvents.addAll(touchEventsBuffer); touchEventsBuffer.clear(); return touchEvents;

The final method, SingleTouchHandler.getTouchEvents(), should be familiar to you, and works similarly to the KeyboardHandler.getKeyEvents() methods. Remember that we need to call this method frequently so that the touchEvents list doesn't get filled up.

0 0

Post a comment