I have developed an Android application that is handling multitouch in a view. I basically track the several MotionEvents that can occur like ACTION_UP, ACTION_MOVE, ... My overwritten onTouch method in the View class looks like this:
public boolean onTouch(View view, MotionEvent event)
{
int action = event.getAction() & MotionEvent.ACTION_MASK;
if (action == MotionEvent.ACTION_DOWN) {
float x = event.getX();
handleTouchStart(view, x);
} else if (action == MotionEvent.ACTION_UP) {
float x = event.getX();
handleTouchEnded(view, x);
} else if (action == MotionEvent.ACTION_POINTER_DOWN) {
int pointer = (event.getAction() & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;
float x = event.getX(pointer);
handleTouchStart(view, x);
} else if (action == MotionEvent.ACTION_POINTER_UP) {
int pointer = (event.getAction() & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;
float x = event.getX(pointer);
handleTouchEnded(view, x);
} else if (action == MotionEvent.ACTION_MOVE) {
int pointer = (event.getAction() & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;
float x = event.getX(pointer);
handleTouchMoved(view, x);
}
return true;
}
On my phone (Samsung Galaxy S), this works flawlessly. For every handleTouchStart(), the appropriate handleTouchEnded() is called. This is crucial for my app. It's a 2D sidescroller with a steering area in the left lower portion of the screen. If - for some reason - the handleTouchEnded() method is not called when the user lifts a finger from the touchscreen, the player's character continues running.
I've received reports from players on other devices (like the HTC Desire) that in rare occasions, the character does indeed continue running in a direction even if they lifted their finger from the steering area on the screen. I concluded that this can only happen if handleTouchEnded() is not called which in turn means that no ACTION_UP (or ACTION_POINTER_UP) event is generated.
Are there device specific implementations of multitouch support? Is there no guarantee that for each ACTION_DOWN (or ACTION_POINTER_DOWN) MotionEvent, an appropriate ACTION_UP (or ACTION_POINTER_UP) MotionEvent is called? Or am I missing something? Is my onTouch implementation even correct?
My broader question would be: are there better ways to handle multitouch touchscreen input for "action"-games? I'm basically mimicking the left and right controls of a gamepad's steering cross. I've found that Android's UI buttons don't offer enough flexibility because they can't track onPress and onRelease events... or do they?