2011-05-17 58 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