When you start writing your first app for the new S60 5th edition platform you’ll find that, among the first things to deal with, there is interface scrolling: when playing with touchscreen devices, users expect to be able to interact with on-screen objects by simple stylus/finger gestures, rather than by an old-fashion, on-screen keyboard.
Today, we’ll see how to implement touch scrolling in Java ME in a simple scenario: scrolling a large Image, that doesn’t fit on the device display.
A sample MIDlet showing this code in action is available on the emulator page: Touch scrollable image in action.
Source Code: ScrollableImageCanvas class
Let’s start defining the main class, that will extend the Canvas object:
public class ScrollableImageCanvas extends Canvas
{
{ |
Now, we define properties that we’ll use to manage:
- image size
- image translation
- user touch interaction
// image-related properties
int imageHeight = 0;
int imageWidth = 0;
Image image = null;
// scroll properties
protected int translationX = 0;
protected int translationY = 0;
// touch properties
protected int lastPointerX = -1;
protected int lastPointerY = -1; |
Class constructor is quite straightforward, and only needs an Image as argument:
public ScrollableImageCanvas(Image image)
{
this.image = image;
this.imageWidth = image.getWidth();
this.imageHeight = image.getHeight();
} |
Also paint() implementation is simple, since it simply draws the given Image at current translation x and y coordinates:
protected void paint(Graphics g)
{
g.setColor(0xffffff);
g.fillRect(0, 0, getWidth(), getHeight());
g.drawImage(image, - translationX, - translationY, Graphics.TOP | Graphics.LEFT);
} |
Finally, we must implement the touch-based scrolling functionality. To do this, we’ll override the 3 pointer handlers provided by Canvas objects:
- pointerPressed: called when the pointer is pressed
- pointerReleased: called when the pointer is released
- pointerDragged: called when the pointer is dragged
protected void pointerPressed(int x, int y)
{
lastPointerX = x;
lastPointerY = y;
}
protected void pointerReleased(int x, int y)
{
lastPointerX = -1;
lastPointerY = -1;
}
protected void pointerDragged(int x, int y)
{
scrollImage(lastPointerX - x, lastPointerY - y);
lastPointerX = x;
lastPointerY = y;
} |
The scrollImage() method implementation follows. What it does is:
- increment the current translation x and y coordinated by the given x and y deltas
- normalize the new translation x and y coordinates, so that Image will not go out of bounds
void scrollImage(int deltaX, int deltaY)
{
if(imageWidth > getWidth())
{
translationX += deltaX;
if(translationX < 0)
translationX = 0;
else if(translationX + getWidth() > imageWidth)
translationX = imageWidth - getWidth();
}
if(imageHeight > getHeight())
{
translationY += deltaY;
if(translationY < 0)
translationY = 0;
else if(translationY + getHeight() > imageHeight)
translationY = imageHeight - getHeight();
}
repaint();
} |
Complete class source code is available here: ScrollableImageCanvas.java.
If you like this article, feel free to rate it on Forum Nokia Wiki.
Further development
A lot of improvements can be done to the code presented in this article. Just some examples are:
- scrollbars: a fundamental element to let the user know how much he can scroll both in vertical and horizontal directions
- smooth scrolling: using some inertia when applying scrolling movement will make the whole scrolling effect a lot more realistic
ernesto61 7:12 pm on December 29, 2008 Permalink
Yes, now it works but every time it is downloading a event, ask the permission. If there are 10 events …ten permits…
ogni volta chiede l’autorizzazione di protezione se scaricare o no l’evento, è molto fastidioso; c’è un modo per levarlo?
pit 10:32 am on December 30, 2008 Permalink
Hi ernesto,
to modify permission settings you should follow these steps:
This way, you will have only 1 permission popup per usage session.
Hope this helps!
Pit
Kearon 5:49 am on January 8, 2009 Permalink
First up – Tops job on a handy little app!
Now here’s a small bug report (maybe)…
Let’s say I have an appointment on 8:30am Friday. It show correctly on Google calendar, but in Gcal (on my N95) it shows and an all-day event on the day before! This s consist=ant with other ‘morning’ appointments – they show as ‘all-day’ events the day before….but drilling down into each event reveals they actually have the correct time and day data (that is, whats showing in google calendar – it’a all OK)…so it’s something to do with how Gcal is reading and displaying the event. Any ideas? I have all my location settings on Google calendar correct for Sydney, Aust (GMT+10).
pit 10:36 am on January 20, 2009 Permalink
Hi Kearon,
have you checked latest version (0.2)? It should have solved many problems with timezone. Let me know if it worked for you
Pit
ManojGaur 2:22 am on February 4, 2009 Permalink
Hello !
I’ve Sony Ericsson K810i model but Gcal latest version is not working bcoz it accepts only 5digits password for gmail account;while I’ve 6digits password gmail account.
Pl help.
Thanks.
pit 10:09 am on February 4, 2009 Permalink
Hi ManojGaur,
this sounds really strange, since password limit is currently set to 255 characters; I use a longer password too, and it works on tested devices. :-\
I’ll check if there are some device-related issues or other possible causes, and let you know asap
Thanks,
Pit
Chris 3:46 pm on March 3, 2009 Permalink
Have you had any progress with a diagnostic version? I would love to get this app working on my Helio Ocean (still having the same connection problem), thanks:)