我試圖創建一個應用程序頂部的項目列表的頂部顯示一些額外的行以「生活搜索」字段:黑莓:如何過濾由ListField表示的行?
當然,我一直在使用a KeywordFilterField with overriden setSize()嘗試那首先。但是這樣做效果不好 - 因爲我無法控制,什麼時候以及如何通過KeywordFilterField調用setSize(),並且這給了我繪圖問題(當我輸入關鍵字並添加了一個新項目時沒有繪製行到列表等)
所以我想「回到根源」,並使用ListField(和頂部BasicEditField),因爲那裏我可以控制自己,何時和如何控制自己調用setSize()。
下面是我簡單的測試代碼 - 的src \ mypackage中\ MyList.java和border.png。
該代碼運行良好,除了篩選問題 - 我將在下面描述。
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 = 3;
BasicFilteredList myFilter = new BasicFilteredList();
Background myBg = BackgroundFactory.createSolidBackground(0x111111);
StringProvider myProvider = new StringProvider("Search");
BasicEditField myFind = new BasicEditField(USE_ALL_WIDTH) {
protected void paint(Graphics g) {
if (getTextLength() == 0) {
g.setColor(Color.LIGHTGRAY);
g.drawText(myProvider.toString(), 0, 0);
}
g.setColor(Color.BLACK);
super.paint(g);
}
};
MyItemList myItems = new MyItemList();
// add 1 row for the "* Empty *" string
ListField myList = new ListField(EXTRA_ROWS + 1) {
protected boolean navigationClick(int status, int time) {
int index = getSelectedIndex();
if (index >= EXTRA_ROWS && myItems.size() > 0) {
String str = ((MyItem) myItems.getAt(
index - EXTRA_ROWS)).toString();
Status.show("You have clicked - " + str);
}
return true;
}
};
Border myBorder = BorderFactory.createBitmapBorder(
new XYEdges(12, 12, 12, 12),
Bitmap.getBitmapResource("border.png"));
public MyScreen() {
getMainManager().setBackground(myBg);
myFind.setBorder(myBorder);
setTitle(myFind);
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.setCallback(new MyListFieldCallback());
add(myList);
myFilter.addDataSet(1, myItems.getElements(), "Test",
BasicFilteredList.COMPARISON_IGNORE_CASE);
}
protected boolean keyChar(char key, int status, int time) {
if (key == Characters.BACKSPACE && myFind.getTextLength() == 0) {
Status.show("Kill kill kill!");
return true;
}
if (myFind.getTextLength() > 0) {
System.err.println("XXX filter for " + myFind.getText());
}
return super.keyChar(key, status, time);
}
private class MyListFieldCallback implements ListFieldCallback {
public void drawListRow(ListField list, Graphics g, int index, int y, int width) {
Font i = getFont().derive(Font.ITALIC);
g.setColor(Color.DIMGRAY);
g.drawLine(0, y-9, width, y-9);
g.setColor(Color.WHITE);
if (index < EXTRA_ROWS) {
g.setFont(i);
g.drawText("Add Item", 0, y, DrawStyle.ELLIPSIS|DrawStyle.HCENTER, width);
return;
}
if (myItems.size() == 0) {
g.setFont(i);
g.drawText(list.getEmptyString(), 0, y, DrawStyle.ELLIPSIS|DrawStyle.HCENTER, width);
return;
}
MyItem item = (MyItem) myItems.getAt(index - EXTRA_ROWS);
g.drawText(item.toString(), 0, y, DrawStyle.ELLIPSIS|DrawStyle.HCENTER, width);
}
public Object get(ListField list, int index) {
return myItems.getAt(index);
}
public int getPreferredWidth(ListField list) {
return Display.getWidth();
}
public int indexOfList(ListField list, String prefix, int start) {
return 0;
}
}
class MyItemList extends SortedReadableList {
public MyItemList() {
super(new MyItem.MyComparator());
}
protected void doAdd(Object obj) {
super.doAdd(obj);
myList.setSize(size() + EXTRA_ROWS);
}
protected boolean doRemove(Object obj) {
// if the list is empty, add 1 row for "* Empty *" string
int size = (size() == 0 ? EXTRA_ROWS + 1 : size() - 1 + EXTRA_ROWS);
myList.setSize(size);
return super.doRemove(obj);
}
protected Object[] getElements() {
return super.getElements();
}
}
}
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 };
}
}
}
我的問題是,我不知道如何添加過濾。例如,當用戶在myFind中輸入「E」時,我的代碼將在keyChar()中檢測到此事件,並且我明白,我將不得不調用myList.setSize(EXTRA_ROWS + 1),因爲會有1過濾結果。
但是如何過濾myList顯示的項目,如何實現呢?
也許我可以用BasicFilteredList及其方法
public void addDataSet(int id,
Object[] objects,
String name,
long style)
,但我不知道如何在這裏適用嗎?
UPDATE:
我添加了一個BasicFilteredList到我的測試上面的代碼,但現在還不能確定如何使用ListField嫁呢。
我想實現你的建議,但不知道如何讓我的矢量(保持原始數據)和SortedReadableList(控股篩選出的結果)同步。 – 2011-05-18 09:18:45
謝謝邁克爾,你有沒有對新代碼有任何建議,我已發佈爲答案? – 2011-05-18 11:56:34