Wednesday, July 16, 2008

J2ME Custom List

Custom List using J2ME CustomItem

Very recently I've undergone with a problem of creating a custom list in j2me. The list should contain items which will not only have three items at three differnt places but also they will contain an image. The image needed to be changed based on some flags. It was a little tough to do as I am very much New Comer int the mobile technologies as well as for the J2Me.My PM got so much angered at me for taking too much time (It took about 2 days for me) that he once even said that It can be doable by even a 12th standard child (I really don't know whether it is true.). But after scolding me for whole a day at last I could survive this problem after taking his help((:-) Thanks to him for his Kind help with (a liitle lot) scold).


For the convinience of the new comers who will not face same problem as me I am putting the solution here itself.


I have created My CustomList by extending CustomItem class. This class is very useful fpr creating new custom item. You can create any type of view using this class. Though you have to have a lot of logic for key handling at your new view.


Some Assumptions For the list are as under:-
1.It holds only 6 item at a time.
2.Right now I only could test only on the WTK default color emulator. There may be    some problems on running same code in other devices or emulators.
3. Though I tried to use as much as the programming technique to compute the width and heights and other stuff, there may are some hard coded stuff as well. e.g. the number of items in the list etc.

I hope This code will be a lot of help for you visitors.

Logic fot the list as under:-
1. Declares a number of variables to be used. There use is mentioned in the comments.
2. Constructor is used to initializes many a thing like height of item etc.
3.The paint method and overridden traverse method are of modt important.
Firstly paint method draws various items recatngle.
paint method is used to draw the items using a loop which loops on from 0 to 5. Then it will takes the string array and draws those strings.
4. The traverse method is used to handle key navigation
     

Now Leave all. Come to point. Here is my code for the custom list:-



/**
*
*/
package date160708;

import java.io.IOException;
import java.util.Vector;

import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.CustomItem;
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;


/**
* @author Administrator
*
*/
public class CustomList extends CustomItem {

/*
* The following array variable contains the strings each of which will be further build an
* array of strings(in this case having length 3), which will be used to draw at differnt places in the same item.
*/
private String [] strData;
/*
* The following variables wll contain height and width of the customlist
*/
private int listHeight;
private int listWidth;

/*
* The following variables contain the num of items to be drawn
*/
private int numRows = 6;
/*
* Mainly there will be one column. If you want to draw a table like thing you can change this ,
* but you will have to make some changes in the code inside paint() method also.
*/
private int numColumns = 1;

/*
* The following variables are used as height and width of the items in custom list
*/
private int hRect;
private int wRect;

/*
* The following will indicate the current items. If you have more than two columns
* then xCurrent will also be changed but since here only one column so this value will not changed.
*/
private int xCurrent = 0;
private int yCurrent = 0;

/*
* This array will contain 0 and 1 values - used for the changes of images.
*/
private int [] imageFlags;

/*
* Image variables
*/
private static Image image1;
private static Image image2;
/*
* Loading images.
*/
static {
try {
image1 = Image.createImage("/single2.png");
image2 = Image.createImage("/single8.png");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

/**
* Constructor
* Description:- initializes different variables
* @param title:- Title of the custom item
* @param strArray :-
* @param width
* @param height
* @param flags
*/
protected CustomList(String title, String [] strArray, int width, int height, int[] flags) {
super("");
this.strData = strArray;
this.hRect = height / 6;
this.wRect = width - 2;
this.imageFlags = flags;

}

/**
* return minimum height requires
*/
protected int getMinContentHeight() {
return (numRows * hRect +1);
}

/**
* returns minimum width
*/
protected int getMinContentWidth() {
return (numColumns * wRect + 2);
}

/**
* return preferred content height
*/
protected int getPrefContentHeight(int arg0) {
return (numRows * hRect +1);
}
/**
* return preferred width
*/
protected int getPrefContentWidth(int arg0) {
return (numColumns * wRect + 2);
}

/*
* paint method used to draw the list items.
*/
protected void paint(Graphics g, int w, int h) {
Font font = g.getFont();
for(int i = 0; i <= numRows; i++) {
g.drawLine(0, i * hRect, numColumns * wRect, i * hRect);
}

for(int i = 0; i <= numColumns; i++) {
g.drawLine(i * wRect, 0, i * wRect, numRows * hRect);
}

int oldColor = g.getColor();
g.setColor(0x00D0D0D0);
g.fillRect((xCurrent * wRect) + 1, (yCurrent * hRect) + 1, wRect - 1, hRect - 1);

g.setColor(oldColor);

for(int i = 0; i < numRows; i++) {
String [] splitArray = createArrayOfStrings(strData[i], '@');
for(int j = 0; j < numColumns; j++) {
int oldClipX = g.getClipX();
int oldClipY = g.getClipY();

int oldClipWidth = g.getClipWidth();
int oldClipHeight = g.getClipHeight();
int x1 = (j * wRect) +2;
if(imageFlags[i] == 1) {
g.drawImage(image1, x1, (i * hRect) + font.getHeight(), Graphics.BOTTOM| Graphics.LEFT);
x1 += image1.getWidth();
} else {
g.drawImage(image2, x1, (i * hRect) + font.getHeight(), Graphics.BOTTOM| Graphics.LEFT);
x1 += image2.getWidth();
}
g.drawString(splitArray[0], x1, (i * hRect) + font.getHeight(),
Graphics.BOTTOM| Graphics.LEFT);

int x2 = getMinContentWidth() - (font.stringWidth(splitArray[1]) + font.charWidth(' '));
g.drawString(splitArray[1], x2 , (i * hRect) + font.getHeight(),
Graphics.BOTTOM| Graphics.RIGHT);

g.drawString(splitArray[2], x1, (i * hRect) +2 * font.getHeight(),
Graphics.BOTTOM| Graphics.LEFT);
// g.setClip((j * boxWidth) + 1, i * boxHeight, boxWidth - 1, boxHeight - 1);
// g.setClip(oldClipX, oldClipY, oldClipWidth, oldClipHeight);
}
}
}

/**
* createArrayOfStrings(String str, char ch)
* Description:- this method is used to create array of strings from a string
* @param str
* @param ch
* @return : a string array
*/

private String[] createArrayOfStrings(String str, char ch) {
Vector vector = new Vector();
int index = str.lastIndexOf(ch);

String[] strArray = null;
for(int i = 0; i < str.length(); i++) {
if(index < 0) {
vector.addElement(str);
break;
} else {
index = str.indexOf(ch);
if(index > 0) {
String elemStr = str.substring(0, index);
str = str.substring(index + 1, str.length());
vector.addElement(elemStr);
}
}
}
strArray = new String[vector.size()];
vector.copyInto(strArray);
return strArray;
}

/**
* travrse is am important method for keyhandling.
*/
protected boolean traverse(int dir, int viewportWidth, int viewportHeight,
int[] visRect_inout) {

switch(dir) {
case Canvas.DOWN : {
if(yCurrent < numRows - 1) {
yCurrent++;
repaint(xCurrent * wRect, (yCurrent - 1) * hRect, wRect, hRect);
repaint(xCurrent * wRect, yCurrent * hRect, wRect, hRect);
}
break;
}
case Canvas.UP : {
if(yCurrent > 0) {
yCurrent--;
repaint(xCurrent * wRect, (yCurrent + 1) * hRect, wRect, hRect);
repaint(xCurrent * wRect, yCurrent * hRect, wRect, hRect);
}
break;
}
}
visRect_inout[0] = xCurrent;
visRect_inout[1] = yCurrent;
visRect_inout[2] = wRect;
visRect_inout[3] = hRect;

return true;
}

}