2011-05-17 67 views
1

我试图创建一个应用程序顶部的项目列表的顶部显示一些额外的行以“生活搜索”字段:黑莓:如何过滤由ListField表示的行?

list

当然,我一直在使用a KeywordFilterField with overriden setSize()尝试那首先。但是这样做效果不好 - 因为我无法控制,什么时候以及如何通过KeywordFilterField调用setSize(),并且这给了我绘图问题(当我输入关键字并添加了一个新项目时没有绘制行到列表等)

所以我想“回到根源”,并使用ListField(和顶部BasicEditField),因为那里我可以控制自己,何时和如何控制自己调用setSize()。

下面是我简单的测试代码 - 的src \ mypackage中\ MyList.javaborder.png

该代码运行良好,除了筛选问题 - 我将在下面描述。

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嫁呢。

回答

2

您必须在代码的某处进行筛选,然后存储结果。覆盖myFind.update(int)以在筛选文本更改时运行筛选。除了myItems之外,您还需要存储myFilteredItems。过滤后,在列表字段上调用setSize()。列表字段绘图代码也需要从已过滤的集合中绘制。那么你应该设置。

+0

我想实现你的建议,但不知道如何让我的矢量(保持原始数据)和SortedReadableList(控股筛选出的结果)同步。 – 2011-05-18 09:18:45

+0

谢谢迈克尔,你有没有对新代码有任何建议,我已发布为答案? – 2011-05-18 11:56:34

2

我已经结束了这段代码,这似乎对我很好(除了下面列出的2个小问题)和绿色答案标记去迈克尔多诺霍他的宝贵意见。

我使用2个Vectors:myData和myFilteredData。而对于UI我使用ListField和BasicEditField:

list

边界。PNG:

border.png

的src \ mypackage中\ 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 { 
    static final int EXTRA_ROWS = 3; 

    Background myBg = BackgroundFactory.createSolidBackground(0x111111); 
    StringProvider myProvider = new StringProvider("Search"); 
    BasicEditField myFind = new BasicEditField(USE_ALL_WIDTH|TextField.NO_NEWLINE) { 
     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); 
     } 

     protected void update(int delta) { 
      filterData(getText()); 
     } 
    }; 

    Vector myData = new Vector(); 
    final static SimpleSortingVector myFilteredData = new SimpleSortingVector(); 

    // 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 && myFilteredData.size() > 0) { 
       String str = ((MyItem) myFilteredData.elementAt(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); 

     myData.addElement(new MyItem(1, "Eins")); 
     myData.addElement(new MyItem(2, "Zwei")); 
     myData.addElement(new MyItem(3, "Drei")); 
     myData.addElement(new MyItem(4, "Vier")); 

     myFilteredData.setSortComparator(new MyItem.MyComparator()); 
     filterData(""); 

     myList.setCallback(new MyListFieldCallback()); 
     add(myList); 
    } 

    private void filterData(String prefix) { 
     myFilteredData.removeAllElements(); 
     if (prefix == null || prefix.length() == 0) { 
      // no prefix specified - copy everything 
      for (int i = myData.size() - 1; i >= 0; i--) { 
       MyItem item = (MyItem) myData.elementAt(i); 
       myFilteredData.addElement(item); 
      } 
     } else { 
      // copy only strings starting with prefix 
      for (int i = myData.size() - 1; i >= 0; i--) { 
       MyItem item = (MyItem) myData.elementAt(i); 
       String name = item.name.toLowerCase(); 

       if (name.startsWith(prefix.toLowerCase())) { 
        myFilteredData.addElement(item); 
       } 
      } 
     } 
     myFilteredData.reSort(); 

     // if the list is empty, add 1 row for "* Empty *" string 
     int size = (myFilteredData.size() == 0 ? EXTRA_ROWS + 1 : myFilteredData.size() + EXTRA_ROWS); 
     myList.setSize(size); 
    } 

    protected boolean keyChar(char key, int status, int time) { 
     if (key == Characters.BACKSPACE && myFind.getTextLength() == 0) { 
      int index = myList.getSelectedIndex(); 
      if (index >= EXTRA_ROWS && myFilteredData.size() > 0) { 
       String str = ((MyItem) myFilteredData.elementAt(index - EXTRA_ROWS)).toString(); 
       Status.show("You're deleting - " + str); 
      } 
      return true; 
     } 

     return super.keyChar(key, status, time); 
    } 

    static class MyListFieldCallback implements ListFieldCallback { 
     public void drawListRow(ListField list, Graphics g, int index, int y, int width) { 
      Font i = g.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 (myFilteredData.size() == 0) { 
       g.setFont(i); 
       g.drawText(list.getEmptyString(), 0, y, DrawStyle.ELLIPSIS|DrawStyle.HCENTER, width); 
       return; 
      } 

      MyItem item = (MyItem) myFilteredData.elementAt(index - EXTRA_ROWS); 
      g.drawText(item.toString(), 0, y, DrawStyle.ELLIPSIS|DrawStyle.HCENTER, width); 
     } 

     public Object get(ListField list, int index) { 
      return myFilteredData.elementAt(index); 
     } 

     public int getPreferredWidth(ListField list) { 
      return Display.getWidth(); 
     } 

     public int indexOfList(ListField list, String prefix, int start) { 
      return myFilteredData.indexOf(prefix, start); 
     } 
    } 
} 

class MyItem { 
    int num; 
    String name; 

    public MyItem(int num, String name) { 
     this.num = num; 
     this.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; 

      String name1 = item1.toString().toLowerCase(); 
      String name2 = item2.toString().toLowerCase(); 

      return name1.compareTo(name2); 
     } 
    } 
} 

我的小问题是:

  1. 为什么我需要减去drawListRow 9()来绘制线?
  2. 为什么脱字符在使用后会在BasicEditField中消失?

screenshot

+0

真的救了我很多时间 – Amy 2014-10-30 12:12:15