Introduction
LWUIT has List Component, but items have the same height, I will show you how to make it dynamic height.
Background
(Optional) You need knowledge of LWUIT lib and J2ME.
Using the Code
Cal. height of List Dynamic
Normal, LWUIT get item has max height in Model, and multiply it with model size. We will cal. height each item in model with method calculateElementSize.
private Dimension calculateElementSize(boolean selected, boolean addMargin) {
int width = 0;
int height = 0;
int elements = Math.min(listSizeCalculationSampleCount, model.getSize());
int marginY = 0;
int marginX = 0;
for (int iter = 0; iter < elements; iter++) {
Component cmp = renderer.getListCellRendererComponent
(this, model.getItemAt(iter), iter, selected, true);
if (cmp instanceof Container) {
cmp.setShouldCalcPreferredSize(true);
}
Dimension d = cmp.getPreferredSize();
width = Math.max(width, d.getWidth());
height = Math.max(height, d.getHeight());
if (iter == 0) {
Style s = cmp.getStyle();
marginY = s.getMargin(TOP) + s.getMargin(BOTTOM);
marginX = s.getMargin(LEFT) + s.getMargin(RIGHT);
}
}
return new Dimension(width + marginX, height + marginY);
}
This function only runs 1 time, but it will be called by paint, many times - by method getElementSize
, so will need modify this method too:
public Dimension getElementSize(boolean selected, boolean addMargin) {
if (selected) {
if (selectedElemSize == null) {
if (model.getSize() == 0) {
if (addMargin) {
return new Label("XXXXXX").getPreferredSizeWithMargin();
}
return new Label("XXXXXX").getPreferredSize();
}
selectedElemSize = calculateElementSize(true, addMargin);
}
return selectedElemSize;
} else {
if (elemSize == null) {
if (model.getSize() == 0) {
Label l = new Label("XXXXXX");
if (addMargin) {
return l.getPreferredSizeWithMargin();
} else {
return l.getPreferredSize();
}
}
elemSize = calculateElementSize(false, addMargin);
}
return elemSize;
}
}
Done. The height of List
, now we cal. each item in Model.
private int calculateElementSize(boolean selected, boolean addMargin, int index, Component cmp) {
int height = 0;
int marginY = 0;
if (isChatRenderCell) {
Dimension d = getHeightComponent(this, model.getItemAt(index), index);
if (d != null) {
height = d.getHeight();
}
} else {
if (cmp == null) {
cmp = renderer.getListCellRendererComponent
(this, model.getItemAt(index), index, selected, true);
}
if (cmp instanceof Container) {
cmp.setShouldCalcPreferredSize(true);
}
height = cmp.getPreferredSize().getHeight();
}
return height + marginY;
}
This method will be called by:
public HashInteger elementSizeCached = new HashInteger();
public int getElementSize(boolean selected, boolean addMargin, int index, Component cmp) {
if (!isDynamicHeight) {
if (HEIGHT_FIXXED < 1) {
HEIGHT_FIXXED = calculateElementSize(true, addMargin, index, cmp);
}
return HEIGHT_FIXXED;
}
if (getModel().getSize() <= 2) {
if (selected) {
return calculateElementSize(true, addMargin, index, cmp);
} else {
return calculateElementSize(false, addMargin, index, cmp);
}
}
if (elementSizeCached != null) {
if (elementSizeCached.containsKey(index)) {
return elementSizeCached.get(index);
} else {
int selectedElemSize = calculateElementSize(true, addMargin, index, cmp);
if (enableCache && selectedElemSize != 0) {
elementSizeCached.put(index, selectedElemSize);
}
return selectedElemSize;
}
} else {
return calculateElementSize(true, addMargin, index, cmp);
}
}
You need:
public HashInteger elementSizeCached = new HashInteger();
It's cached....
We will replace all getElementSize
on default code of LWUIT by our method.
And, every time LWUIT paint item, it will cal, position, height...we will modify this.
public void calculateComponentPosition(int index, int defaultWidth,
Rectangle rect, Dimension rendererSize, Dimension selectedSize, boolean beforeSelected) {
Style style = getStyle();
int initialY = 0;
int initialX = style.getPadding(false, LEFT);
boolean rtl = isRTL();
if (rtl) {
initialX += getSideGap();
}
int selection = getCurrentSelected();
if (rect == null) {
return;
}
Dimension d = rect.getSize();
int selectedDiff;
if (rendererSize == null) {
return;
}
if (selectedSize == null) {
return;
}
int height = rendererSize.getHeight();
selectedDiff = selectedSize.getHeight() - height;
rect.setX(initialX);
d.setHeight(height);
d.setWidth(defaultWidth);
int y = 0;
if (index == 0) {
y = 0;
} else {
if (!isDynamicHeight) {
if (HEIGHT_FIXXED == -1) {
HEIGHT_FIXXED = getElementSize(false, true, index, null);
}
y = (index) * HEIGHT_FIXXED;
} else {
if (positionElement != null && positionElement.containsKey(index)) {
y = positionElement.get(index);
} else {
if (positionElement != null && positionElement.containsKey(index)) {
y = positionElement.get(index);
y += getElementSize(false, true, index - 1, null);
} else {
int prevIndex = index - 1;
if (prevIndex == 0) {
y = getElementSize(false, true, 0, null);
} else if (positionElement.containsKey(prevIndex)) {
int postion = positionElement.get(prevIndex);
y += (postion + getElementSize(false, true, prevIndex, null));
} else {
for (int i = 0; i < index; i++) {
y += getElementSize(false, true, i, null);
}
}
}
}
if (enableCache) {
positionElement.put(index, y);
}
}
}
rect.setY(y + initialY);
if (index == selection) {
d.setHeight(d.getHeight() + selectedDiff);
}
}
Very simple, we will see:
public HashInteger positionElement = new HashInteger();
It's cached....
LWUIT has painted a item which shows on viewport of screen, and this will be calc by pointerSelect.
public int pointerSelect(int x, int y) {
Style style = getStyle();
y = y - getAbsoluteY();
Dimension rendererSize = null;
int width = getWidth() - style.getPadding(isRTL(),
RIGHT) - style.getPadding(isRTL(), LEFT) - getSideGap();
Rectangle pos = new Rectangle();
for (int i = getEndBufferOffset(); i >= getStartBufferOffset(); i--) {
rendererSize = new Dimension(DEFAULT_WIDTH,
getElementSize(true, true, i, null));
calculateComponentPosition(i, width, pos,
rendererSize, rendererSize, i <= getCurrentSelected());
if (y >= pos.getY() &&
y <= pos.getY() + rendererSize.getHeight()) {
return i;
}
}
return getModel().getSize();
}
At this point, basically, all items have a height of up... and remember "clear cached if your model has changed"....
You can download the zip file from the link at the top of this article.
Enjoy it!
Thanks.