Multi-touch is the ability to detect touch events with 2 or more fingers. Android supports multi-touch from version 2.0 onwards. Most common multi-touch gesture is pinch zoom. With Pinch zoom, you can zoom in or out the content by squeezing or pull apart the fingers. We can implement multi-touch in Android using either onTouch events or ScaleGestureDetector.
To View.onTouchEvent is called when we touch the screen. This method has one MotionEvent parameter. This represents the touch event that occurred. The MotionEvent.getAction() method returns the event action. There are different event actions like ACTION_DOWN, ACTION_MOVE, ACTION_UP, ACTION_POINTER_DOWN, ACTION_POINTER_UP, etc. MotionEvent.getX() and MotionEvent.getY() returns x and y position of the event respectively.
ACTION_TOUCH will be generated whenever we touch the screen with one finger (primary pointer). ACTION_UP is generated when the finger has left the screen. This is for single touch. When we touch the screen with two fingers, the first touch detected is considered as the primary pointer and all others are considered as non-primary pointer. For the primary pointer (first touch detected) ACTION_TOUCH is generated and for the non-primary pointers (second touch onwards) ACTION_POINTER_DOWN is generated. When we move the fingers ACTION_MOVE will be generated. When the non-primary pointer left the screen, ACTION_POINTER_UP is generated.
To find now many pointers are there for an event, we can use MotionEvent.getPointerCount() method. This will return how many pointers are there for the event. The getX() and getY() methods has another variant which accepts a pointer id, i.e. MotionEvent.getX(pointerid) and MotionEvent.getY(pointerid) which returns the X and Y coordinates of the pointer with given pointerid. Note that we are passing pointer id not pointer index. The method MotionEvent.getPointerId(index) returns the pointer id of the pointer at the specified index. The index ranges from 0 to getPointerCount() – 1. Now we have X and Y coordinates of the different pointers involved in the multi-touch gesture and we can use this to implement actions like zoom-in, zoom-out, etc.
ScaleGestureDetector class detects gestures with more than two fingers. We use this class the same way we use the GestureDetector class, i.e. we create and instance of the class and on View.onTouchEvent we call the ScaleGestureDetector.onTouchEvent method. The ScaleGestureDetector uses callback interface ScaleGestureDetector.OnScaleGestureListener to report the events occurred. This interface has following three methods:
boolean onScaleBegin(ScaleGestureDetector detector) boolean onScale(ScaleGestureDetector detector) void onScaleEnd(ScaleGestureDetector detector)
The onScaleBegin method is called when two-finger gesture is detected. We have to return true to indicate we have handled this event and all the other methods should be called. If we return false then the ScaleGestureDetector will not call other methods.
The onScale method is called when we move the fingers. Note that this event will not be called when you return false from onScaleBegin callback method.
The onScaleEnd is called when the gesture is finished, i.e. then the fingers left the screen.
All these methods have one parameter ScaleGestureDetector which is instance of the ScaleGestureDetector reported the event.
The ScaleGestureDetector has different methods like, getCurrentSpan(), getFocusX(), getFocusY(), etc. The getCurrentSpan() method returns the current distance between the fingers. The getFocusX() and getFocusY() methods returns the focal point’s (middle point) X and Y coordinates respectively. Using this information we can implement the pinch-zoom gesture. Refer the reference links for more details.
The sample application is a simple one which draws a line between different pointers when you touch the screen with two fingers. The pinch-zoom is not implemented in this application but can be done with minimal effort. See the reference links for an example of pinch-zoom.