在ListField中显示额外的行

时间:2011-05-09 13:36:06

标签: blackberry listfield draw-list

我正在尝试在ListField的顶部显示一个额外的行 - 名为“Add Item”,它几乎可以工作,但是我的数据的最后一行“Item 4”没有显示。

Screenshot, 1 row is missing

您如何解决此问题?

请参阅下面我非常简单的测试代码 MyList.java

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);
    }
}

我尝试添加 myList.setSize(5); ,但得到Vector.elementAt抛出的ArrayIndexOutOfBoundsException(4)

更新

关于Michael的建议我已经从ObjectListField切换到KeywordFilterField(这是我在实际程序中实际使用的),现在我可以调用 myList.setSize(5)而不会抛出任何异常。

但最后一行仍未显示:

screenshot

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 };
        }
    }
}

我有一种感觉, setSize(4)(而不是5)在中间被调用 - 因为我看到最后一行,然后它再次消失。

谢谢! 亚历

3 个答案:

答案 0 :(得分:1)

您不想使用ObjectListField,将类型层次结构中的一个级别上升到ListField,然后您可以根据需要执行setSize()。

答案 1 :(得分:0)

我想这应该有效:

public MyScreen() {
    setTitle("How to display an extra row?");
    myList.set(new String[] { "Add Item", "Item 1","Item 2","Item 3","Item 4"});
    add(myList);
}

或者我错过了什么? :)

答案 2 :(得分:0)

这是我自己的解决方案 - 覆盖ListField的setSize():

enter image description here

(上面的屏幕截图有EXTRA_ROWS = 3,仍然可以正常工作)。

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;

    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 void setSize(int count) {
            super.setSize(count + EXTRA_ROWS);
        }
    };

    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());
        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 };
        }
    }
}