Understanding Touch Events

Whenever I first learn a new API, I like to first put in some code to dump everything out so I can get a feel for what the methods do and in what order events happen. So let's start with that. First add a call to the dumpEvent() method inside onTouch():

Download Touchv1/src/org/example/touch/Touch.java

@Override public boolean onTouch(View v, MotionEvent event) { // Dump touch event to log dumpEvent(event);

return true; // indicate event was handled

Note that we need to return true to indicate to Android that the event has been handled. Next, define the dumpEvent() method. The only parameter is the event that we want to dump.

Download Touchv1/src/org/example/touch/Touch.java

/** Show an event in the LogCat view, for debugging */ private void dumpEvent(MotionEvent event) {

String names[] = { "DOWN", "UP", "MOVE", "CANCEL", "OUTSIDE",

"P0INTER_D0WN", "POINTER_UP", "7?", "8?", "9?" }; StringBuilder sb = new StringBuilder(); int action = event.getAction();

int actionCode = action & MotionEvent.ACTI0N_MASK; sb.append("event AOT0N_").append(names[actionCode]); if (actionCode == MotionEvent.ACTI0N_P0INTER_D0WN

|| actionCode == MotionEvent.ACTI0N_P0INTER_UP) { sb.append("(pi'd ").append(

action >> MotionEvent.ACTI0N_P0INTER_ID_SHIFT); sb.append(')");

for (int i = 0; i < event.getPointerCount(); i++) { sb.append("#").append(i);

sb.append("(pi'd ").append(event.getPointerId(i)); sb.append(")=").append((int) event.getX(i)); sb.append(",").append((int) event.getY(i)); if (i + 1 < event.getPointerCount()) sb.append(";");

sb.append("j"); Log.d(TAG, sb.toString());

Output will go to the Android debug log, which you can see by opening the LogCat view (see Section 3.10, Debugging with Log Messages, on page 69).

The easiest way to understand this code is to run it. Unfortunately, you can't run this program on the emulator (actually you can, but the emulator doesn't support multi-touch, so the results won't be very interesting). Therefore, hook up a real phone to your USB port, and run the sample there (see Section 1.4, Running on a Real Phone, on page 28).

When I tried it on my phone and performed a few quick gestures, I received the following output:

Line 1 event ACTI0N_D0WN[#0(pid 0)=135,179] event ACTI0N_M0VE[#0(pid 0)=135,184] event ACTI0N_M0VE[#0(pid 0)=144,205] event ACTI0N_M0VE[#0(pid 0)=152,227] 5 event ACTI0N_P0INTER_D0WN(pid 1)[#0(pid 0)=153,230;#1(pid 1)=380,538] event ACTI0N_M0VE[#0(pid 0)=153,231;#1(pid 1)=380,538]

event ACTI0N_M0VE[#0(pid 0)=155,236;#1(pid 1)=364,512] event ACTI0N_M0VE[#0(pid 0)=157,240;#1(pid 1)=350,498] event ACTI0N_M0VE[#0(pid 0)=158,245;#1(pid 1)=343,494] 10 event ACTI0N_P0INTER_UP(pid 0)[#0(pid 0)=158,247;#1(pid 1) = 336,484] event ACTI0N_M0VE[#0(pid 1)=334,481] event ACTI0N_M0VE[#0(pid 1)=328,472] event ACTI0N_UP[#0(pid 1)=327,471]

Here's how to interpret the events:

• On line 1 we see an ACTION_DOWN event, so the user must have pressed one finger on the screen. The finger was positioned at coordinates x=135, y=179, which is near the upper left of the display. You can't tell yet whether they're trying to do a tap or a drag.

• Next, starting on line 2, there are some ACTION_MOVE events, indicating the user moved their finger around a bit to those coordinates given in the events. (It's actually very hard to put your finger on the screen and not move it at all, so you'll get a lot of these.) By the amount moved, you can tell the user is doing a drag gesture.

• The next event, ACTION_POINTER_DOWN on line 5, means the user pressed down another finger. "pid 1" means that pointer ID 1 (that is, finger number 1) was pressed. Finger number 0 was already down, so we now have two fingers being tracked on the screen. In theory, the Android API can support up to 256 fingers at once, but the first crop of Android 2.x phones is limited to 2.3 The coordinates for both fingers come back as part of the event. It looks like the user is about to start a pinch zoom gesture.

• Here's where it gets interesting. The next thing we see is a series of ACTION_MOVE events starting on line 6. Unlike before, now we have two fingers moving around. If you look closely at the coordinates, you can see the fingers are moving closer together as part of a pinch zoom.

• Then on line 10, we see an ACTION_POINTER_UP on pid 0. This means that finger number 0 was lifted off the screen. Finger number 1 is still there. Naturally, this ends the pinch zoom gesture.

• We see a couple more ACTION_MOVE events starting on line 11, indicating the remaining finger is still moving around a little. If you compare these to the earlier move events, you'll notice a dif-

3. Although the idea of 256 fingers may seem silly outside of Men in Black headquarters, keep in mind that Android is designed for a wide variety of devices, not just phones. If you have a tabletop-sized screen with several people gathered around it, you could easily have more than a handful of fingers on the display.

ferent pointer ID is reported. Unfortunately, the touch API is so buggy you can't always count on that (see the "Warning: Multibugs Ahead" sidebar). • Finally, on line 13, we get an ACTION_UP event as the last finger is removed from the screen.

Now the code for dumpEvent() should make a little more sense. The getAction() method returns the action being performed (up, down, or move). The lowest 8 bits of the action is the action code itself, and the next 8 bits is the pointer (finger) ID, so we have to use a bitwise AND (&) and a right shift (>>) to separate them.

Then we call the getPointerCount( ) method to see how many finger positions are included. getX() and getY() return the X and Y coordinates, respectively. The fingers can appear in any order, so we have to call getPointerId() to find out which fingers we're really talking about.

That covers the raw mouse event data. The trick, as you might imagine, is in interpreting and acting on that data.

0 0

Post a comment