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:

Be Sociable, Share!