Quite a bit of time is passed since the last Java ME tutorial.. so It’s time for something new, don’t you think?
Today we’ll see how it is possible to implement a simple Canvas based List, with the following features:
- customizable style (colors, margins, font)
- vertical scrolling
- image and text support (as for standard Java ME Lists)

It is possible to see this code in action on the emulator page.
Writing the code
First thing you should define some style-related properties, that will be used to paint the List items. Name of single properties is self-explaining.
int linePadding = 2;
int margin = 2;
int padding = 2;
Font font = Font.getDefaultFont();
int bgColor = 0xffffff;
int foreColor = 0x000000;
int foreSelectedColor = 0xffffff;
int backColor = 0xffffff;
int backSelectedColor = 0x0000ff;
int borderWidth = 3;
int borderColor = 0x000000;
int borderSelectedColor = 0xff0000; |
Now, here are some internal properties, that will be used to handle list items content and positioning.
// will contain item splitted lines
String[][] itemLines = null;
// will hold items image parts
Image[] images = null;
// will hold selected item index
public int selectedItem = 0;
// these will hold item graphical properties
int[] itemsTop = null;
int[] itemsHeight = null;
// these will hold List vertical scrolling
int scrollTop = 0;
final int SCROLL_STEP = 40; |
Now, here is the CanvasList constructor. Its arguments are (similarly to javax.microedition.lcdui.List constructor):
- the screen’s title
- set of strings specifying the string parts of the List elements
- set of images specifying the image parts of the List elements
This article will not cover the handling of different types of Lists (e.g.: exclusive, multiple, ..).
public CanvasList(String title, String[] items, Image[] imageElements)
{
setTitle(title);
this.images = imageElements;
itemLines = new String[items.length][];
itemsTop = new int[itemLines.length];
itemsHeight = new int[itemLines.length];
for(int i = 0; i < itemLines.length; i++)
{
// get image part of this item, if available
Image imagePart = getImage(i);
// get avaiable width for text
int w = getItemWidth() - (imagePart != null ? imagePart.getWidth() + padding : 0);
// and split item text into text rows, to fit available width
itemLines[i] = getTextRows((String) items[i], font, w);
}
} |
Here are the 2 utility methods found in the CanvasList constructor:
public int getItemWidth()
{
return getWidth() - 2 * borderWidth - 2 * padding - 2 * margin;
}
Image getImage(int index)
{
return images != null && images.length > index ? images[index] : null;
} |
Now, here is the paint() method:
protected void paint(Graphics g)
{
// paint List background
g.setColor(bgColor);
g.fillRect(0, 0, getWidth(), getHeight());
// translate accordingly to current List vertical scroll
g.translate(0, - scrollTop);
int top = 0;
g.setFont(font);
// loop List items
for(int i = 0; i < itemLines.length; i++)
{
int itemRows = itemLines[i].length;
Image imagePart = getImage(i);
int itemHeight = itemRows * font.getHeight() + linePadding * (itemRows - 1);
itemsTop[i] = top;
itemsHeight[i] = itemHeight;
// is image part higher than the text part?
if(imagePart != null && imagePart.getHeight() > itemHeight)
{
itemHeight = imagePart.getHeight();
}
itemHeight += 2 * padding + 2 * borderWidth;
g.translate(0, top);
if(borderWidth > 0)
{
// paint item border
g.setColor(i == selectedItem ? borderSelectedColor : borderColor);
g.fillRect(margin, margin, getWidth() - 2 * margin, itemHeight);
}
// paint item background
g.setColor(i == selectedItem ? backSelectedColor : backColor);
g.fillRect(margin + borderWidth, margin + borderWidth, getWidth() - 2 * margin - 2 * borderWidth, itemHeight - 2 * borderWidth);
// has this item an image part?
if(imagePart != null)
{
g.drawImage(imagePart, margin + borderWidth + padding, margin + borderWidth + padding, Graphics.TOP | Graphics.LEFT);
}
// paint item text rows
g.setColor(i == selectedItem ? foreSelectedColor : foreColor);
int textLeft = margin + borderWidth + padding + (imagePart != null ? imagePart.getWidth() + padding : 0);
for(int j = 0; j < itemRows; j++)
{
g.drawString(itemLines[i][j], textLeft, margin + borderWidth + padding + j * (linePadding + font.getHeight()), Graphics.TOP | Graphics.LEFT);
}
g.translate(0, - top);
top += itemHeight + 2 * margin;
}
// finally, translate back
g.translate(0, scrollTop);
} |
And finally, to handle user key events, here is the keyPressed() event:
protected void keyPressed(int key)
{
int keyCode = getGameAction(key);
// is there 1 item at least?
if(itemLines.length > 0)
{
// going up
if(keyCode == Canvas.UP)
{
// current item is clipped on top, so can scroll up
if(itemsTop[selectedItem] < scrollTop)
{
scrollTop -= SCROLL_STEP;
repaint();
}
// is there a previous item?
else if(selectedItem > 0)
{
selectedItem--;
repaint();
}
}
//going down
else if(keyCode == Canvas.DOWN)
{
// current item is clipped on bottom, so can scroll down
if(itemsTop[selectedItem] + itemsHeight[selectedItem] >= scrollTop + getHeight())
{
scrollTop += SCROLL_STEP;
repaint();
}
// is there a following item?
else if(selectedItem < itemLines.length - 1)
{
selectedItem++;
repaint();
}
}
}
} |
About the getTextRows() method, you can grab an implementation (but you could find a lot of other ones on the Web) on this other article written some time ago: J2ME Scrollable Text.
How to use CanvasList class
Here is a sample usage of CanvasList class, that will display a list (without image parts):
String[] items = new String[]{"Item 1", "Item 2", "Item 3"};
CanvasList myCanvas = new CanvasList("Test canvas", items, null); |
To add images to your items, it’s necessary to instantiate an Image array, and pass it to CanvasList constructor as its third argument:
Image[] images = null;
try
{
images = new Image[]{
Image.createImage("/item1.png"),
Image.createImage("/item2.png"),
Image.createImage("/item3.png")
};
}
catch(Exception e)
{
e.printStackTrace();
}
String[] items = new String[]{"Item 1", "Item 2", "Item 3"};
CanvasList myCanvas = new CanvasList("Test canvas", items, images); |
Related resources
You can download full CanvasList source code here: CanvasList.java
Ugur 9:31 am on October 1, 2008 Permalink
Congrats Alessandro, great to see you among us as well!
pit 1:23 pm on October 1, 2008 Permalink
Thanks Ugur!
Leonardo 10:36 am on October 2, 2008 Permalink
Ciao Alessandro,
Congrats!!!
Leo
pit 9:10 am on October 3, 2008 Permalink
Thanks Leo!
Honored to be in such a good company
Raj 1:34 pm on October 13, 2008 Permalink
Hey Congrats!!!!!! pit