Layout Management in J2ME
Posted by Namrata on June 6, 2008
One day Anuj (Our Product Boss :)) came to me with some layouts and asked to support all of the following layouts in J2ME application.
All these layouts are combinations of images and strings. Initially, I was worried about the implementation, but after going through the layouts couple of times, I thought Gridbag layout of swings would support all these combinations. I knew how Gridbag worked but didn’t know how I could arrange components in horizontal and vertical cells. The most challenging issue was J2ME’s memory limitations for both jar and jad. We can develop a full fledged Gridbag layout class just like swing but some issues could arise.
- Potential big class size
- We will have to keep minimum instances of components for heap issues, the best case being one instance per component.
So let’s start engineering with minimum requirement of arranging cells.
-
Here is the list of items which we need to consider while adding components in layout:
- Starting horizontal cell
- Starting vertical cell
- Number of horizontal cells required
- Number of vertical cells required
- Component
All these will go as parameters in the add method.
add(component, start_horizontal_cell, start_vert_cell, no_of_horizontal_cell, no_of_vert_cell)
To store these components, we can have an array of components or some custom defined array list.
Each cell will have some height and width say CellH =20 and CellW = 20.
Thats all.. we are ready to construct a layout class which will hold images and strings.
Say we have two UI classes for rendering a single image MyImage and a single string as label MyLabel.
Here is the code piece for our layout class. We are considering this layout class itself as a component which will make it easy for us to add it to a container.
/**
* A class which can hold any component, which can be rendered at any position
* in this component’s boundary depending upon its cell location.
* This is a Gridbag layout. To create a label of this type with any
* component,
* e.g to add MyLabel at cell position row 0, column 0 with
* 2 horizontal cells and 1 vertical cell,
*
* TestLabel label = new TestLabel();
* myCanvas.addComponent(label);
* MLabel strLabel = new MLabel(”First label”);
* label.add(strLabel, (byte)0, (byte)0, (byte)2, (byte)0);
*/
public class TestLayout extends Component{
private MyArrayList components; //user defined array list
public int cellW = 20;
public int cellH = 20;
public int noOfRowCells;
public int noOfColumnCells;
public boolean showGrid;
/**
* Creates a new instance of TestLabel
* @Param boolean tells whether this Label will should have
* canvas width or width that is neccesary to component
*/
public TestLabel() {
height = 20;
width = canvasW;
components = new MArrayList();
calculateDimensions();
isStatic = false;
}
/**
* this method renders component
* @param Graphics
**/
protected void renderComponent(Graphics g) {
int posX = compX;
int posY = compY;
int size = components.size();
g.setColor(MMasterColors.GREY);
if(showGrid){
for(int i = 0; i < noOfRowCells ; i ++){
g.drawLine(compX, posY, width, posY);
posY += cellH;
}
g.drawLine(compX, posY, width, posY);
for(int i = 0; i < noOfColumnCells ; i ++){
g.drawLine(posX, compY, posX, compY + height);
posX += cellW;
}
}
for(int i = 0; i < size ; i ++){
((MComponent)components.get(i)).renderComponent(g);
}
}
/**
* This method calculates dimensions
**/
protected void calculateDimensions() {
noOfColumnCells = width / cellW;
noOfRowCells = height / cellH;
}
/**
* A method to add component to AdvLabel
* @param MComponent component which is to be added
* @Param byte rowNo cell at row level
* @Param byte Columno cell at Column level
* @Param byte no of horizontal rows required
* @Param byte no of vertical rows required
* @param byte alignment
**/
public void addComponent(MComponent comp, byte rowNo, byte ColumnNo, byte noOfHoriCells, byte noOfVertCells){
components.add(comp);
if(height < ((ColumnNo + noOfVertCells) * cellH))// setting height if needed
height = (ColumnNo + noOfVertCells) * cellH;
calculateDimensions();
int tempX = 0;
int tempY = 0;
tempX = compX + ((rowNo * cellW) + (((noOfHoriCells * cellW) - comp.getComponentWidth()) / 2));
tempY = compY + (((((noOfVertCells * cellH) - comp.getComponentHeight())/ 2) + (ColumnNo * cellH)));
comp.setComponentXY(tempX, tempY);
}
}
public class Component{
public int componentX;
public int componentY;
protected int height;
protected int width = canvasW;
protected void renderComponent(Graphics g) {
}
protected void calculateDimensions() {
}
/**
*Mutator method to set x, y positions
*@param x X co-ordinate
*@param y Y co-ordinate
*/
public void setComponentXY(int x, int y) {
componentX = x;
componentY = y;
}
/**
*returns component height
*@return height
*/
public int getComponentHeight() {
return height;
}
public int getComponentWidth() {
return width;
}
}
Above code is at very primary level which will fulfill our requirement of arranging components in a grid. We can then add (if memory permits
) advanced features like:
- Providing key navigations
- Maintaining and highlighting current component
- Aligning components within the mentioned cells
- Providing more ui specific things like borders, background colors etc.
- and so on….
