【问题标题】:Displaying extra rows in a ListField在 ListField 中显示额外的行
【发布时间】:2011-05-09 13:36:06
【问题描述】:

我试图在 ListField 顶部显示一个额外的行 - 称为“添加项目”,它几乎可以工作,但我的数据的最后一行“项目 4”没有显示。

你会如何解决这个问题?

请看下面我非常简单的测试代码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(4) 引发的 ArrayIndexOutOfBoundsException

更新:

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

但是最后一行还是没有显示出来:

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)在两者之间被调用 - 因为我看到最后一行一会儿,然后它又消失了。

谢谢! 亚历克斯

【问题讨论】:

  • 而且我学到了 KeywordFilterField.setKeyword(null) 比 setKeyword("") 更好的艰难方法

标签: blackberry listfield draw-list


【解决方案1】:

您不想使用 ObjectListField,在类型层次结构中上一级到ListField,然后您可以随意执行 setSize()。

【讨论】:

  • 我已经切换到 KeywordFilterField 并且现在可以调用 setSize(),但最后一行仍然丢失。我已经更新了上面的测试用例
  • ListField 不是抽象的。我建议你直接使用它。
【解决方案2】:

我想这应该可行:

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

还是我错过了什么? :)

【讨论】:

  • 不幸的是,这对我来说是个糟糕的解决方案——因为在我的真实程序中(相对于上面的简化测试用例),我正在使用 KeywordFilterField 显示某些对象(不是字符串)的 SortedReadableList。如果我将“添加项目”添加到该 SortedReadableList,我将无法将其作为 KeywordFilterField 中的第一行进行排序。所以我希望有另一种解决方案......
  • 所以也许这只是实现排序的问题,所以结果总是首先出现“添加项目”?
【解决方案3】:

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

(上面的屏幕截图有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 };
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-03
    • 1970-01-01
    • 1970-01-01
    • 2021-04-03
    相关资源
    最近更新 更多