Building a J2ME sliding menu with text and images
Whatever you’re building, a game or an application, you always need a menu to let users navigate through sections of your MIDlet.
This article will show how to build a menu with text and icons, and with a nice sliding effect to go from one menu item to another. You can see the final effect on the emulator page: J2ME Sliding Menu in action.
Source code: SlideIconsMenu class
As always, let’s start defining our class:
public class SlideIconsMenu { } |
Now, we define some appearance-related properties, that can be customized to change menu colors and font.
// selected item index public int selectedIndex = 0; // icon label color public int textColor = 0xff0000; // menu bg color public int bgColor = 0xffffff; // icon label font public Font textFont = Font.getDefaultFont(); // menu right and left Images public Image slideRightImage = null; public Image slideLeftImage = null; |
And some other properties, that will be internally used by the menu class itself, to handle content and the sliding animation:
// menu size int width = 0; int height = 0; // item labels String[] labels = null; // item icons Image[] icons = null; // previous item index (during menu translation) int prevIndex = 0; // menu sliding translation properties public int translationDuration = 500; long startTranslationTime = 0; |
Now, let’s define the menu constructor. We need a constructor that will accept these arguments:
- a set of item labels
- a set of images, one for each item
- the menu width
- and the menu height
public SlideIconsMenu(String[] labels, Image[] icons, int width, int height) throws Exception { this.width = width; this.height = height; this.labels = labels; this.icons = icons; slideRightImage = Image.createImage("/slide_right.png"); slideLeftImage = Image.createImage("/slide_left.png"); } |
The constructor also creates 2 Images to represent the left and right sliding arrows, that will be used to indicate more items on the menu left/right side. So, in your code, you must adapt those image paths to match existing ones within your project.
Now we must handle item change, by letting our menu slide with a nice transition. To do this, we’ll manage the item change with the following slideItem() method:
public void slideItem(int delta) { if(!isTranslating() && selectedIndex + delta >= 0 && selectedIndex + delta < labels.length) { prevIndex = selectedIndex; selectedIndex += delta; startTranslationTime = System.currentTimeMillis(); } } public boolean isTranslating() { return prevIndex != selectedIndex; } |
And finally, since we need to paint our menu, here is its paint() method:
public void paint(Graphics g) { g.setColor(bgColor); g.fillRect(0, 0, width, height); g.setColor(textColor); if(selectedIndex > 0) { g.drawImage(slideLeftImage, 2, height / 2, Graphics.LEFT | Graphics.VCENTER); } if(selectedIndex < icons.length - 1) { g.drawImage(slideRightImage, width - 2, height / 2, Graphics.RIGHT | Graphics.VCENTER); } g.drawString(labels[selectedIndex], width / 2, height - 2, Graphics.BOTTOM | Graphics.HCENTER); g.setClip(slideLeftImage.getWidth(), 0, width - 2 * slideLeftImage.getWidth(), height); if(selectedIndex != prevIndex) { int diff = (int)(System.currentTimeMillis() - startTranslationTime); if(diff > translationDuration) { diff = translationDuration; } int coeff = selectedIndex > prevIndex ? 1 : - 1; int currentX = width / 2 - coeff * diff * width / translationDuration; int nextX = currentX + width * coeff; g.drawImage(icons[prevIndex], currentX, height / 2, Graphics.VCENTER | Graphics.HCENTER); g.drawImage(icons[selectedIndex], nextX, height / 2, Graphics.VCENTER | Graphics.HCENTER); if(diff >= translationDuration) { prevIndex = selectedIndex; } } else { g.drawImage(icons[selectedIndex], width / 2, height / 2, Graphics.VCENTER | Graphics.HCENTER); } } |
Sample usage
Here’s a sample Canvas that uses the SlideIconsMenu class. The main steps are:
- the menu constructions
- the key handling, done within the Canvas keyPressed() method
- the menu repainting, done periodically, to allow the sliding transition to be smoothly drawn
import javax.microedition.lcdui.Canvas; import javax.microedition.lcdui.Graphics; import javax.microedition.lcdui.Image; public class SlideIconsCanvas extends Canvas implements Runnable { SlideIconsMenu menu = null; public SlideIconsCanvas() { Image[] im = new Image[3]; try { im[0] = Image.createImage("/item0.png"); im[1] = Image.createImage("/item1.png"); im[2] = Image.createImage("/item2.png"); menu = new SlideIconsMenu( new String[]{"Item 1", "Item 2", "Item 3"}, im, getWidth(), getHeight() ); new Thread(this).start(); } catch(Exception e) { e.printStackTrace(); } } protected void paint(Graphics g) { menu.paint(g); } public void keyPressed(int key) { int gameKey = getGameAction(key); if(gameKey == Canvas.RIGHT) { menu.slideItem(1); } else if(gameKey == Canvas.LEFT) { menu.slideItem(- 1); } } public void run() { try { while(true) { repaint(); synchronized(this) { wait(100L); } } } catch(Exception e) { e.printStackTrace(); } } } |
Download source code
You can download full source code here:
- SlideIconsMenu.java: menu source code
- SlideIconsCanvas.java: sample Canvas using the SlideIconsMenu
deanet 7:21 pm on September 24, 2008 Permalink
wew … nice code
Stella 8:26 am on October 1, 2008 Permalink
Hi ,
this screen is brilliant, i was wondering if you could come up with a design that is similar to the carousel interface of yahoo GO!. this design is quite close to that
byeeeee
Stella
pit 9:04 am on October 1, 2008 Permalink
Thanks for your feedback
@stella: check out this other article, if it could suit your needs
http://www.jappit.com/blog/2008/04/24/building-a-fisheye-menu-in-j2me-with-jsr-226/
Stella 7:04 am on October 15, 2008 Permalink
yep i seen that. but that uses JSR226 right what about devices that dont have JSR266
Regards
Stella
Tyler 1:22 pm on April 30, 2009 Permalink
Hi jappit;
i have look at your code but i think you always refresh screen and wait 100ms. right? It uses 100% processor.
jermaine 3:23 am on September 29, 2010 Permalink
thanks for this bit of code…but uhm, how do i run this? i copied the source codes but i dont know where to place the jar files…