The Frame Animator API allows MIDlets to trigger linear drag and kinetic scroll animations in response to drag and flick gestures. The Frame Animator API does not draw the UI updates for an animation, but rather calculates the motion interpolation for the animation. To draw the animation, use the standard LCDUI methods for rendering graphics.
Use the Frame Animator API together with the Gesture API. For example on MIDlets that show you how to do this, see section Touch UI - FavoriteArtists.
The Frame Animator API consists of the following classes and interfaces (packaged as part of the Nokia UI API):
Use the FrameAnimator
class to trigger drag and scroll animations.
Use
the FrameAnimatorListener
interface to implement
a listener for receiving a notification for each new frame in the
animation. Use the notifications to define the corresponding UI update.
The Frame Animator API is supported since Nokia UI API 1.1b.
The Frame Animator API is supported since Series 40 6th Edition Feature Pack 1.
Note: The following instructions
and code snippets only focus on the Frame Animator API. For instructions
on creating a full MIDlet, see sections 01 Getting started and MIDlet
lifecycle. For instructions on using the Canvas
class in a MIDlet, see section Canvas.
To use drag and scroll animations in your MIDlet:
Create a UI element that receives drag and flick events, and define handlers for these events. For instructions, see sections Receiving gesture events and Handling gesture events.
Register a FrameAnimatorListener
for the UI element using the FrameAnimator.register
method. The FrameAnimatorListener
notifies the MIDlet of each frame
update in the triggered animation.
The following
code snippet registers a MyFrameAnimatorListener
(see
step 4 of this example) for a custom Canvas
class
called GestureCanvas
.
// Import the necessary classes import com.nokia.mid.ui.frameanimator.FrameAnimator; import com.nokia.mid.ui.gestures.GestureInteractiveZone; import com.nokia.mid.ui.gestures.GestureRegistrationManager; import javax.microedition.lcdui.Canvas; public class GestureCanvas extends Canvas { // FrameAnimator for registering a FrameAnimatorListener private FrameAnimator frameAnimator; // Variables for keeping track of the animation coordinates private int currentX; private int currentY; public GestureCanvas() { // Register a GestureListener and GestureInteractiveZone // ... // Specify int referenceX, int referenceY, short maxFps, short maxPps // ... this.currentX = referenceX; this.currentY = referenceY; // Create a MyFrameAnimatorListener instance MyFrameAnimatorListener myFrameAnimatorListener = new MyFrameAnimatorListener(this); // Create a FrameAnimator instance and // use it to register the MyFrameAnimatorListener instance frameAnimator = new FrameAnimator(); frameAnimator.register(referenceX, referenceY, maxFps, maxPps, myFrameAnimatorListener); } // Return and update the animation coordinates public int getCurrentX() { return this.currentX; } public void setCurrentX(int newX) { this.currentX = newX; } public int getCurrentY() { return this.currentY; } public void setCurrentY(int newY) { this.currentY = newY; } // Return the FrameAnimator instance public FrameAnimator getFrameAnimator() { return this.frameAnimator; } // Create the Canvas UI by implementing the paint method and // other necessary methods (see the LCDUI instructions) // ... }
Registering a FrameAnimatorListener
requires that you specify the following values:
referenceX
specifies the starting x-coordinate
for the animation. The x-coordinates passed to the FrameAnimatorListener.animate
method are initially calculated from referenceX
.
referenceY
specifies the starting y-coordinate
for the animation. The y-coordinates passed to the FrameAnimatorListener.animate
method are initially calculated from referenceY
.
maxFps
specifies the maximum number of frames
per second (fps) for the animation. This controls how often the FrameAnimatorListener.animate
method is called per second
at maximum. The value is a percentage of the default platform value
for maximum fps. To retrieve the default platform value, use the com.nokia.mid.ui.frameanimator.fps
system
property:
defaultMaxFps = (Short)Integer.parseInt(System.getProperty("com.nokia.mid.ui.frameanimator.fps"));
The supported maxFps
values are 0
-200
. 0
and 100
indicate that the default platform value is used.
For example,
if your MIDlet can only handle 10 fps, but the native platform rate
is 20 fps, ensure that maxFps
is set to 50
or less. A value of 50
indicates 50% of the native
platform rate of 20 fps, amounting to 10 fps, the MIDlet's maximum
fps.
maxPps
specifies the maximum number of pixels
per second (pps) for a kinetic scroll animation. This controls the
distance in pixels between consecutive animation frame updates. The
value is a percentage of the default platform value for maximum pps.
To retrieve the default platform value, use the com.nokia.mid.ui.frameanimator.pps
system
property.
defaultMaxPps = (Short)Integer.parseInt(System.getProperty("com.nokia.mid.ui.frameanimator.pps"));
The supported maxPps
values are 0
-200
. 0
and 100
indicate that the default platform values is used.
For example,
if your MIDlet can only handle 10 pps, but the native platform rate
is 20 pps, ensure that maxPps
is set to 50
or less. A value of 50
indicates 50% of the native
platform rate of 20 pps, amounting to 10 pps, the MIDlet's maximum
pps.
Trigger the animations from the corresponding gesture event handlers:
To trigger a linear drag animation, use the FrameAnimator.drag
method.
To trigger a kinetic scroll animation, use the FrameAnimator.kineticScroll
method.
Calling the methods results in one or more calls to the FrameAnimatorListener.animate
method, which describes the
animation for the platform to draw (see step 4 of this example).
The following code snippet triggers the animations directly from
a GestureListener
implementation called MyGestureListener
.
// Import the necessary classes import com.nokia.mid.ui.frameanimator.FrameAnimator; import com.nokia.mid.ui.gestures.GestureEvent; import com.nokia.mid.ui.gestures.GestureInteractiveZone; import com.nokia.mid.ui.gestures.GestureListener; public class MyGestureListener implements GestureListener { public void gestureAction(Object container, GestureInteractiveZone gestureInteractiveZone, GestureEvent gestureEvent) { // Cast the container as a GestureCanvas for easy access GestureCanvas gestureCanvas = (GestureCanvas)container; // Retrieve the FrameAnimator instance from the UI element FrameAnimator frameAnimator = gestureCanvas.getFrameAnimator(); // Trigger the correct animation for the received event switch (gestureEvent.getType()) { case GestureInteractiveZone.GESTURE_DRAG: { // Set the target coordinates for the animation by // retrieving the current animation coordinates // and adding the drag distance to them int newX = gestureCanvas.getCurrentX() + gestureEvent.getDragDistanceX(); int newY = gestureCanvas.getCurrentY() + gestureEvent.getDragDistanceY(); frameAnimator.drag(newX, newY); }; break; case GestureInteractiveZone.GESTURE_FLICK: { frameAnimator.kineticScroll(gestureEvent.getFlickSpeed(), FrameAnimator.FRAME_ANIMATOR_FREE_ANGLE, FrameAnimator.FRAME_ANIMATOR_FRICTION_MEDIUM, gestureEvent.getFlickDirection()); }; break; } } }
For more information about implementing the GestureListener
interface, see section Handling gesture
events.
Tip: If you find that a drag animation
works too slowly and does not match the physical drag action, consider
implementing counters for keeping track of the distance moved after
each animate
call, and then using these counters
to align the animation with the corresponding drag events. For instructions
on how to create the counters, see article Getting started with the Gesture API & FrameAnimator
API in the Nokia Developer Wiki.
Implement the FrameAnimatorListener
registered in step 2. Use the FrameAnimatorListener.animate
method to define
the UI updates for the animation. The animate
method
is called every time the MIDlet calls either FrameAnimator.drag
or FrameAnimator.kineticScroll
. For a kinetic scroll
animation, the animate
method is called at regular
intervals with the updated position and other information describing
the current state of the animation, that is, its current frame.
The following code snippet creates the framework for
the MyFrameAnimatorListener
custom class.
// Import the necessary classes import com.nokia.mid.ui.frameanimator.FrameAnimator; import com.nokia.mid.ui.frameanimator.FrameAnimatorListener; public class MyFrameAnimatorListener implements FrameAnimatorListener { private GestureCanvas gestureCanvas; public MyFrameAnimatorListener(GestureCanvas gestureCanvas) { this.gestureCanvas = gestureCanvas; } // Implement the animate method public void animate(FrameAnimator frameAnimator, int x, int y, short delta, short deltaX, short deltaY, boolean lastFrame) { // Update the current animation coordinates this.gestureCanvas.setCurrentX(x); this.gestureCanvas.setCurrentY(y); // Refresh the UI based on received animation events // ... } }
Each animate
call returns the following
parameters:
frameAnimator
specifies the FrameAnimator
instance that triggered the animation.
x
specifies the current x-coordinate of the
animation. For a kinetic scroll animation, this value is initially
calculated from referenceX
used in registering the FrameAnimatorListener
.
y
specifies the current y-coordinate of the
animation. For a kinetic scroll animation, this value is initially
calculated from referenceY
used in registering the FrameAnimatorListener
.
delta
specifies the distance in pixels from
the previous position. This indicates the distance moved since the
previous animate
call.
deltaX
specifies the distance in pixels between
the current x-coordinate and the x-coordinate from the previous animate
call. This indicates the horizontal distance moved
since the previous animate
call.
deltaY
specifies the distance in pixels between
the current y-coordinate and the y-coordinate from the previous animate
call. This indicates the vertical distance moved
since the previous animate
call.
lastFrame
specifies whether this is the end
of the current animation. true
indicates that this
is the last frame of the animation, while false
indicates
that this is not the last frame.
After the animation has ended, the last coordinates are stored
in memory for as long as the FrameAnimatorListener
remains registered. Therefore a new animation using the same FrameAnimatorListener
instance begins where the last one
ended.