Layout managers in LWUIT are a remarkably powerful tool, I won't go into all the elaborate ways in which you can modify the layout in LWUIT since this is covered rather well in the tutorial and developer guide. Instead I will try to show something that is a bit under documented, mostly because its almost exactly like its Swing/AWT equivalent: building a layout manager.
A layout manager contains all the logic for positioning LWUIT components, it essentially traverses a LWUIT container and positions components absolutely based on internal logic. When we build our own component we need to take padding into consideration, when we build the layout we need to take margin into consideration. Building a layout manger involves two simple methods: layoutContainer & getPreferredSize.
layoutContainer is invoked whenever LWUIT decides the container needs rearranging, LWUIT tries to avoid calling this method and only invokes it at the last possible moment. Since this method is generally very expensive (imagine the recursion with nested layouts...), LWUIT just marks a flag indicating layout is "dirty" when something important changes and tries to avoid "reflows".
getPreferredSize allows the layout to determine the size desired for the container, this might be a difficult call to make for some layout managers that try to provide both flexibility and simplicity. Most of flow layout bugs stem from the fact that this method is just impossible to implement for flow layout. The size of the final layout won't necessarily match the requested size (it probably won't) but the requested size is taken into consideration, especially when scrolling and also when sizing parent containers.
This is a layout manager that just arranges components in a center column aligned to the middle:
/**Here is a simple example of using it:
* Layout manager that arranges components in a center column
*
* @author Shai Almog
*/
public class CenterLayout extends Layout {
public void layoutContainer(Container parent) {
int components = parent.getComponentCount();
Style parentStyle = parent.getStyle();
int centerPos = parent.getLayoutWidth() / 2 + parentStyle.getMargin(Component.LEFT);
int y = parentStyle.getMargin(Component.TOP);
for(int iter = 0 ; iter < components ; iter++) {
Component current = parent.getComponentAt(iter);
Dimension d = current.getPreferredSize();
current.setSize(d);
current.setX(centerPos - d.getWidth() / 2);
Style currentStyle = current.getStyle();
y += currentStyle.getMargin(Component.TOP);
current.setY(y);
y += d.getHeight() + currentStyle.getMargin(Component.BOTTOM);
}
}
public Dimension getPreferredSize(Container parent) {
int components = parent.getComponentCount();
Style parentStyle = parent.getStyle();
int height = parentStyle.getMargin(Component.TOP) + parentStyle.getMargin(Component.BOTTOM);
int marginX = parentStyle.getMargin(Component.RIGHT) + parentStyle.getMargin(Component.LEFT);
int width = marginX;
for(int iter = 0 ; iter < components ; iter++) {
Component current = parent.getComponentAt(iter);
Dimension d = current.getPreferredSize();
Style currentStyle = current.getStyle();
width = Math.max(d.getWidth() + marginX + currentStyle.getMargin(Component.RIGHT) +
currentStyle.getMargin(Component.LEFT), width);
height += currentStyle.getMargin(Component.TOP) + d.getHeight() +
currentStyle.getMargin(Component.BOTTOM);
}
Dimension size = new Dimension(width, height);
return size;
}
}
Form f = new Form("Centered");
f.setLayout(new CenterLayout());
for(int iter = 1 ; iter < 20 ; iter++) {
f.addComponent(new Button("Button: " + iter));
}
f.addComponent(new Button("Really Wide Button Text!!!"));
f.show();