I'm trying to display an extra row at the top of a ListField - called "Add Item" and it almost works, but the very last row "Item 4" of my data is not displayed.
How would you fix this issue?
Please see my very simple test code MyList.java below:
package mypackage;
import java.util.*;
import net.rim.device.api.collection.*;
import net.rim.device.api.collection.util.*;
import net.rim.device.api.system.*;
import net.rim.device.api.ui.*;
import net.rim.device.api.ui.component.*;
import net.rim.device.api.ui.container.*;
import net.rim.device.api.ui.decor.*;
import net.rim.device.api.util.*;
public class MyList extends UiApplication {
public static void main(String args[]) {
MyList app = new MyList();
app.enterEventDispatcher();
}
public MyList() {
pushScreen(new MyScreen());
}
}
class MyScreen extends MainScreen {
ObjectListField myList = new ObjectListField() {
public void drawListRow(ListField list,
Graphics g,
int index,
int y,
int width) {
if (index == 0) {
Font i = getFont().derive(Font.ITALIC);
g.setFont(i);
g.drawText("Add Item", 0, y);
} else {
String str = (String) get(this, index - 1);
g.drawText(str, 0, y);
}
}
protected boolean navigationClick(int status, int time) {
int index = myList.getSelectedIndex();
String str = (index > 0 ? (String) get(this, index - 1) :
"Add item");
Status.show("You have clicked: " + str);
return true;
}
};
public MyScreen() {
setTitle("How to display an extra row?");
myList.set(new String[]{"Item 1","Item 2","Item 3","Item 4",});
// myList.setSize(5);
add(myList);
}
}
I've tried adding myList.setSize(5); but get an ArrayIndexOutOfBoundsException thrown by Vector.elementAt(4)
UPDATE:
On Michael's suggestion I've switched from ObjectListField to KeywordFilterField (which is what I actually use in my real program) and now I can call myList.setSize(5) without any exception being thrown.
But the last row is still not displayed:
package mypackage;
import java.util.*;
import net.rim.device.api.collection.*;
import net.rim.device.api.collection.util.*;
import net.rim.device.api.system.*;
import net.rim.device.api.ui.*;
import net.rim.device.api.ui.component.*;
import net.rim.device.api.ui.container.*;
import net.rim.device.api.ui.decor.*;
import net.rim.device.api.util.*;
public class MyList extends UiApplication {
public static void main(String args[]) {
MyList app = new MyList();
app.enterEventDispatcher();
}
public MyList() {
pushScreen(new MyScreen());
}
}
class MyScreen extends MainScreen {
static final int EXTRA_ROWS = 1;
MyItemList myItems = new MyItemList();
KeywordFilterField myList = new KeywordFilterField() {
protected boolean navigationClick(int status, int time) {
int index = getSelectedIndex();
String str = (index < EXTRA_ROWS ? "Add item" :
((MyItem) getElementAt(index - EXTRA_ROWS)).toString());
Status.show("You have clicked - " + str);
return true;
}
};
public MyScreen() {
setTitle(myList.getKeywordField());
myList.setSourceList(myItems, new MyItem.MyProvider());
myItems.doAdd(new MyItem(1, "Eins"));
myItems.doAdd(new MyItem(2, "Zwei"));
myItems.doAdd(new MyItem(3, "Drei"));
myItems.doAdd(new MyItem(4, "Vier"));
myList.setSourceList(myItems, new MyItem.MyProvider());
myList.setCallback(new MyListFieldCallback());
myList.setSize(myItems.size() + EXTRA_ROWS);
myList.updateList();
add(myList);
}
private class MyListFieldCallback implements ListFieldCallback {
public void drawListRow(ListField list, Graphics g, int index, int y, int width) {
if (index < EXTRA_ROWS) {
Font i = getFont().derive(Font.ITALIC);
g.setFont(i);
g.drawText("Add Item", 0, y);
return;
}
if (index >= EXTRA_ROWS) {
MyItem item = (MyItem) ((KeywordFilterField) list).getElementAt(index - EXTRA_ROWS);
g.drawText(item.toString(), 0, y);
return;
}
g.drawText(list.getEmptyString(), 0, y);
}
public Object get(ListField listField, int index) {
return null;
}
public int getPreferredWidth(ListField listField) {
return 0;
}
public int indexOfList(ListField listField, String prefix, int start) {
return 0;
}
}
}
class MyItemList extends SortedReadableList {
public MyItemList() {
super(new MyItem.MyComparator());
}
protected void doAdd(Object obj) {
super.doAdd(obj);
}
protected boolean doRemove(Object obj) {
return super.doRemove(obj);
}
}
class MyItem {
int _num;
String _name;
public MyItem(int num, String name) {
_num = num;
_name = name;
}
public String toString() {
return _num + ": " + _name;
}
static class MyComparator implements Comparator {
public int compare(Object obj1, Object obj2) {
MyItem item1 = (MyItem) obj1;
MyItem item2 = (MyItem) obj2;
return item1.toString().compareTo(item2.toString());
}
}
static class MyProvider implements KeywordProvider {
public String[] getKeywords(Object obj) {
MyItem item = (MyItem) obj;
return new String[]{ Integer.toString(item._num), item._name };
}
}
}
I have a feeling, that setSize(4) (instead of 5) is called inbetween - because I see the last row for a moment and then it disappears again.
Thank you! Alex
Here is my own solution - override the setSize() of the ListField:
(the screenshot above has EXTRA_ROWS = 3, which still works ok).