You can implement multipoint touch functionality on Series 40 full touch devices using:
Pointer event methods (in case you want to maintain compatibility with Symbian devices)
Multipoint touch and the Multipoint Touch API are supported on Series 40 full touch devices with Java Runtime 2.0.0 for Series 40 or newer. For information about multipoint touch on Symbian devices, see section Multipoint touch.
The Multipoint Touch API allows MIDlets to implement multipoint
touch functionality on Canvas
and Canvas
-based elements, such as GameCanvas
and FullCanvas
, and on CustomItem
. The API
registers multipoint touch interaction as multipoint touch events,
each of which involves one or more touch points ("pointers"). Each
touch point corresponds to a finger pressed against the screen. The
API keeps track of each touch point separately, meaning MIDlets can
track individual fingers as they move across the screen. Each touch
point is associated with a unique ID, current x and y coordinates,
and a current state, which can be one of the following:
POINTER_PRESSED
indicates that a finger is
pressed against the screen, thus creating a new touch point. This
corresponds to a touch action. This state is not registered for stops
during a drag action.
POINTER_DRAGGED
indicates that a pressed finger
is being dragged over the screen. This corresponds to a drag action.
If the user stops dragging but keeps the finger pressed
against the screen, the state of the touch point is still registered
as POINTER_DRAGGED
. However, the coordinates of the
touch point do not change from its preceding POINTER_DRAGGED
state. Thus, to handle stops during a drag action, check whether
the coordinates of a dragged touch point change between multipoint
touch events.
POINTER_RELEASED
indicates that a pressed
finger is lifted from the screen, thus ending the touch point. This
corresponds to a release action.
You can retrieve the current state and coordinates of a touch point at any time, not just during a multipoint touch event. However, you need the ID of the touch point, which you can only retrieve from a multipoint touch event involving the touch point.
Tip: If you want to implement a simple pinch action, use the Gesture API instead, since it provides a ready-made pinch implementation.
Different devices support a different number of simultaneous
touch points. To determine the maximum number of simultaneous touch
points supported by a device, call the static MultipointTouch.getMaxPointers
method.
For an example MIDlet that shows you how to implement multipoint touch functionality using the Multipoint Touch API, see Paint.
The Multipoint Touch API consists of the following classes and interfaces (packaged as part of the Nokia UI API):
Use the MultipointTouch
class to access touch point information,
determine the maximum number of simultaneous touch points supported
by a device, or register or remove a MultipointTouchListener
.
Use the MultipointTouchListener
interface to implement
a listener for receiving a notification whenever a multipoint touch
event occurs.
The Multipoint Touch API also provides the com.nokia.mid.ui.multipointtouch.version
system property, which MIDlets can use to query the Multipoint Touch
API version supported by the device.
The Multipoint Touch API is supported since Nokia UI API 1.6.
To implement multipoint touch functionality using the Multipoint Touch API:
Check that the
Multipoint Touch API is supported on the device by querying the com.nokia.mid.ui.multipointtouch.version
system property:
if (System.getProperty("com.nokia.mid.ui.multipointtouch.version") != null) { // API is supported: Can implement multipoint touch functionality } else { // API is not supported: Cannot implement multipoint touch functionality }
Retrieve the MultipointTouch
singleton instance by calling the static getInstance
method:
MultipointTouch mpt = MultipointTouch.getInstance();
The singleton instance is only needed for registering (and removing) a multipoint touch event listener.
Register a MultipointTouchListener
for the MIDlet by calling the MultipointTouch.addMultipointTouchListener
method. The MultipointTouchListener
notifies the MIDlet of multipoint
touch events.
The following code snippet registers
an MPTCanvas
object as a MultipointTouchListener
. The MPTCanvas
class is assumed to extend Canvas
and implement MultipointTouchListener
.
MPTCanvas mptCanvas = new MPTCanvas(); mpt.addMultipointTouchListener(mptCanvas);
Create the UI element for which you want to implement the multipoint touch functionality.
The following code snippet creates the framework for
a Canvas
class called MPTCanvas
that
implements MultipointTouchListener
.
// Import the necessary classes import com.nokia.mid.ui.multipointtouch.MultipointTouch; import com.nokia.mid.ui.multipointtouch.MultipointTouchListener; import javax.microedition.lcdui.*; // Import other classes required by the Canvas implementation // ... public class MPTCanvas extends Canvas implements CommandListener, MultipointTouchListener { // Implement Canvas functionality and MultipointTouchListener // ... }
Implement the MultipointTouchListener
registered in step 3. The MultipointTouchListener
interface
defines the pointersChanged
method, which is called
every time the platform triggers a multipoint touch event. A multipoint
touch event involves a change in one or more touch points, that is,
a change in their coordinates or state, or both. The pointersChanged
method returns the IDs of the changed touch points. Use these IDs
to access the current coordinates and states of the changed touch
points, and use the coordinate and state information to update the
MIDlet UI accordingly.
The following code snippet
implements a pointersChanged
method that calls separately
defined methods for updating the MIDlet UI in response to the multipoint
touch event. (The implementation of the update methods is not part
of this example.) The code snippet assumes that the containing class
is set to implement MultipointTouchListener
.
public void pointersChanged(int[] pointerIds) { int pointerId; int x; int y; int state; // Loop through the changed touch points for(int i=0; i<pointerIds.length; i++) { // Get the touch point ID pointerId = pointerIds[i]; // Get the touch point state state = MultipointTouch.getState(pointerId); // Get the touch point x and y coordinates x = MultipointTouch.getX(pointerId); y = MultipointTouch.getY(pointerId); // Handle the UI update based on the touch point state, // ID, and coordinates switch(state) { case MultipointTouch.POINTER_PRESSED: // A new finger was pressed against the screen updatePress(pointerId, x, y); break; case MultipointTouch.POINTER_DRAGGED: // A pressed finger was dragged over the screen updateDrag(pointerId, x, y); break; case MultipointTouch.POINTER_RELEASED: // A pressed finger was lifted from the screen updateRelease(pointerId, x, y); break; default: break; } } }
You can use the following LCDUI Canvas
pointer event methods on Series 40 full touch devices to register
the x and y coordinates of two or more simultaneous touch points:
pointerPressed
is called when a finger is
pressed against the screen, thus creating a new touch point. This
corresponds to a touch action.
pointerDragged
is called when a pressed finger
is being dragged over the screen. This corresponds to a drag action.
pointerReleased
is called when a pressed
finger is lifted from the screen, thus ending the touch point. This
corresponds to a release action.
Using the pointer event methods ensures compatibility with multipoint touch MIDlets developed for Symbian devices. However, the Series 40 implementation differs from the Symbian implementation in two important ways:
The com.nokia.pointer.number
system property
is not supported on Series 40 devices. This means that you cannot
use the system property to track individual touch points. To receive
multipoint touch events in your MIDlet with these pointer event methods,
you must implement your own logic. For example, you must implement
your own logic for buffering the touch points when you need to display
simultaneous touches on the screen.
For an example implementation, see section Example: Implementing multipoint touch functionality using the pointerPressed method.
Multipoint touch events are enabled by default on Series 40
devices. You do not need to set the EnableMultiPointTouchEvents
value for the Nokia-UI-Enhancement
attribute in
the MIDlet JAD file (unless, of course, you also want to run the MIDlet
on Symbian devices).
Different devices support a different number of simultaneous
touch points. To determine the maximum number of simultaneous touch
points supported by a device, call the static MultipointTouch.getMaxPointers
method.
Tip: If you do not need to maintain compatibility with Symbian devices, use the Multipoint Touch API instead, as it provides a ready-made implementation for handling multipoint touch interaction.
This example demonstrates how concurrent touches using two fingers can be displayed on the screen as small dots at the coordinate points the user has tapped on. The logic can be easily expanded to match the number of maximum pointers supported by the device.
A TimerTask
is used to repetitively
wait for very short intervals until a buffer array storing the coordinates
of the multitouch points is filled. The paint
method
is then called to draw all the points sequentially to the screen.
inactivityCounter = new Point[2]; //2-point multi-touch implementation inactivityTimer = new Timer(); inactivityTimer.schedule( new TimerTask() { public void run() { //if one or more points are waiting to be painted if(current >=0 ) { repaint(); } } }, 0, 20); //20 millisecond period for gathering points
This logic is necessary because concurrency issues arise inside
the paint
method when the painted points are pressed,
dragged or released.
The inactivityCounter
array
is the buffer array storing the multitouch points. Point
is a custom made class storing the x
and y
coordinates that define the touched point on the screen:
class Point { public int x; public int y; public Point(int x, int y) { this.x = x; this.y = y; } public int getX() { return x; } public int getY() { return y; } }
The pointerPressed
method fills
the inactivityCounter
array with points.
protected void pointerPressed(int x, int y) { current ++; //the total number of points is increased per point press inactivityCounter[current] = new Point(x, y); //adds this point to the buffer array }
Finally the paint
method is called
from the scheduled TimerTask
to draw blue-painted
circles on the screen.
Note: The paint
method
is called for the first time when the canvas is activated and displayed,
and the array has not yet been filled with points. So a control should
be in place to prevent any attempt to traverse the array which would
result in a NullPointerException
.
public void paint(Graphics g){ g.setColor(0, 0, 255); /* This control ensures that no null pointer exceptions occurs * the first time the canvas is displayed and painted when * the buffer array is not yet filled with points */ if(current >= 0) { //paints the current item g.fillArc(inactivityCounter[current].x, inactivityCounter[current].y, 10, 10, 0, 360); current--; //one point less to be painted } }