I have read many other posts on ListField scrolling and they have helped me to get this far, but now I am stuck. I have my list field in a VerticalManager with scrolling working. I have it set up so that there are 5 visible rows in the ListField. However, when I scroll past the last visible row (currently there are a total of 9 rows in the list), the rows no longer paint the text of the row. I have developed a Custom ListField implementation that has a foreground and background color. The idea is that as each row is focused, the foreground and background color switch - the selected row has navy background with white text and unselected rows have white background with navy text. Works great for the visible rows, but when I scroll past row 5 to reveal the invisible rows, they are just painting with the navy background and no white text. Here is my custom list field class (which was based off of something I found either on a forum or in the knowledge base):
Code:
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.XYRect;
import net.rim.device.api.ui.component.ListField;
public class ColoredListField extends ListField
{
private boolean hasFocus = false;
private final int fixedWidth;
private int fgcolor;
private int bgcolor;
private final int fixedHeight;
public ColoredListField(int width, int height, int fgcolor, int bgcolor)
{
this.fixedWidth = width;
this.fixedHeight = height;
this.fgcolor = fgcolor;
this.bgcolor = bgcolor;
}
public int getPreferredWidth()
{
return fixedWidth;
}
public void layout(int width, int height)
{
setExtent(fixedWidth, fixedHeight);
}
public int moveFocus(int amount, int status, int time)
{
invalidate(getSelectedIndex());
return super.moveFocus(amount, status, time);
}
public void onFocus(int direction)
{
hasFocus = true;
super.onFocus(direction);
invalidate();
}
public void onUnfocus()
{
hasFocus = false;
super.onUnfocus();
invalidate();
}
public void paint(Graphics graphics)
{
// Get the current clipping region as it will be the only part that
// requires repainting
XYRect redrawRect = graphics.getClippingRect();
if (redrawRect.y < 0)
throw new IllegalStateException(
"The 'y' variable of the clipping " +
"rectangle is < 0: " + redrawRect.y);
// If the ListField has focus determine the selected row.
int rowHeight = getRowHeight();
int currEntry = redrawRect.y / rowHeight;
int lastVisibleEntry = (redrawRect.y + redrawRect.height - 1) / rowHeight;
lastVisibleEntry = Math.min(lastVisibleEntry, getSize() - 1);
int y = currEntry * rowHeight;
int curSelected = hasFocus ? getSelectedIndex() : -1;
// Draw each row
for (; currEntry <= lastVisibleEntry; ++currEntry)
{
graphics.setColor(currEntry == curSelected ? bgcolor : fgcolor);
graphics.fillRect(0, y, redrawRect.width, rowHeight);
graphics.setColor(currEntry == curSelected ? fgcolor : bgcolor);
graphics.drawText(getCallback().get(this, currEntry).toString(), 0,
y);
// Assign new values to the y axis moving one row down.
y += rowHeight;
}
}
}
Here is how I instantiate the class:
Code:
private int screenW = Graphics.getScreenWidth();
private int screenH = Graphics.getScreenHeight();
private int listWidth = (int) (screenW * 0.95);
private int listHeight = (int) (screenH * 0.4);
private ColoredListField myListField = new ColoredListField(
listWidth, listHeight, selectedFGColor, selectedBGColor);
Also, here is my callback:
Code:
private static class DiaryEntryListCallback implements ListFieldCallback
{
private DiaryEntry[] diaryEntryList;
public DiaryEntryListCallback() throws Exception
{
diaryEntryList = new DiaryEntry[0];
init();
}
public void init() throws Exception
{
DiaryEntry[] tmpDiaryEntryList =
DiaryDAO.instance().getDiaryEntriesAsArray(true);
if (tmpDiaryEntryList != null && tmpDiaryEntryList.length > 0)
diaryEntryList = tmpDiaryEntryList;
else
{
diaryEntryList = new DiaryEntry[1];
diaryEntryList[0] = new DiaryEntry("No data",
Calendar.getInstance());
}
}
public void init(DiaryEntry[] diaryEntries) throws Exception
{
diaryEntryList = diaryEntries;
}
public int getNumberOfRows()
{
return diaryEntryList.length;
}
public void drawListRow(ListField l, Graphics g, int index, int y, int w)
{
// drawing text is handled by the custom list field implementation
}
public Object get(ListField listField, int index)
{
return diaryEntryList[index];
}
public int getPreferredWidth(ListField listField)
{
return listField.getPreferredWidth();
}
public int indexOfList(ListField listField, String prefix, int start)
{
int size = diaryEntryList.length;
for (int i = 0; i < size; i++)
{
DiaryEntry currEntry = (DiaryEntry) diaryEntryList[i];
if (currEntry.getEntryText().toLowerCase().startsWith(
prefix.toLowerCase()))
return i;
}
return listField.getSelectedIndex();
}
}
And here is where I build the main screen, adding the list field and other fields to it:
Code:
private void createMainScreen()
{
mainMgr = new ColoredVerticalManager(selectedBGColor,
Manager.USE_ALL_HEIGHT);
listMgr = new ColoredVerticalManager(
selectedBGColor,
Manager.VERTICAL_SCROLL | Manager.VERTICAL_SCROLLBAR);
mainMgr.add(diaryEntriesLabel = new FixedWidthLabelField(
"Diary Entries:", listWidth, -1, selectedFGColor, selectedBGColor));
try
{
listCallback = new DiaryEntryListCallback();
diaryEntriesListField.setSize(listCallback.getNumberOfRows());
diaryEntriesListField.setCallback(listCallback);
diaryEntriesListField.setFocusListener(new DiaryFocusListener());
listMgr.add(diaryEntriesListField);
mainMgr.add(listMgr);
}
catch (Exception e)
{
Dialog.alert("Error loading diary entry list: " + e.getMessage());
}
mainMgr.add(selectedEntryLabel = new FixedWidthLabelField(
"Selected Entry:", -1, -1, selectedFGColor, selectedBGColor));
mainMgr.add(diaryEntry);
add(mainMgr);
}
Any clues as to why when scrolling past the visible rows, it stops painting?
Thanks,
Steve