Search code examples
javablackberryjava-medrop-down-menujde

How do you make a dropdown list that displays images to the user instead of text?


The ObjectChoiceField field meets all my requirements but it is not pretty.

This is what I have:

String pets[] = {"Dog", "Cat", "Duck" };
ObjectChoiceField dd = new ObjectChoiceField("My Pet",pets,0,ObjectChoiceField.FIELD_LEFT);

But I would prefer to have pictures in the dropdown. My understanding is that the object array must contain objects that support the toString method. There are got to be a way to do I see it in other apps, I just can't find the correct object in the API.

It doesn't have to be an ObjectChoiceField.


Solution

  • I would use custom ButtonField and PopupScreen. Two reasons:

    • in mobile design it's better to use screen effectively, and classic desktop dropdown control seems to be less sufficient than popup, at least for complex items (image + text)
    • it's easier :)

    alt text http://img405.imageshack.us/img405/3746/dropdown.jpg

    DropDownItem:

    class DropdownItem {
     Bitmap mBitmap;
     String mName;
    
     public DropdownItem(Bitmap bitmap, String name) {
      this.mBitmap = bitmap;
      this.mName = name;
     }
    }
    

    Custom ButtonField:

    class BitmapButtonField extends ButtonField {
     protected DropdownItem mItem;
     boolean mTextItem;
     int mWidth;
     int mHeight;
    
     public BitmapButtonField(DropdownItem item, boolean textItem) {
      super(CONSUME_CLICK);
      mItem = item;
      mTextItem = textItem;
      mWidth = mItem.mBitmap.getWidth() + 6
        + (mTextItem ? getFont().getAdvance(mItem.mName) + 6 : 0);
      mHeight = mItem.mBitmap.getHeight() + 6;
      setMargin(0, 0, 0, 0);
      setPadding(0, 0, 0, 0);
      setBorder(BorderFactory.createSimpleBorder(new XYEdges(0, 0, 0, 0)));
      setBorder(VISUAL_STATE_ACTIVE, BorderFactory
        .createSimpleBorder(new XYEdges(0, 0, 0, 0)));
     }
    
     protected void paint(Graphics graphics) {
      int color = (getVisualState() == VISUAL_STATE_FOCUS) ? Color.LIGHTGREY
        : Color.DARKGRAY;
      graphics.setColor(color);
      graphics.drawRect(1, 1, mWidth - 2, mHeight - 2);
      graphics.drawBitmap(3, 3, mItem.mBitmap.getWidth(), mItem.mBitmap
        .getHeight(), mItem.mBitmap, 0, 0);
      if (mTextItem)
       graphics.drawText(mItem.mName, mItem.mBitmap.getWidth() + 6, 3);
    
     }
    
     public int getPreferredWidth() {
      return mWidth;
     }
    
     public int getPreferredHeight() {
      return mHeight;
     }
    
     protected void layout(int width, int height) {
      setExtent(mWidth, mHeight);
     }
    }
    

    Dropdown control itself:

    class DDImagesButton extends BitmapButtonField implements FieldChangeListener {
     DropdownItem[] mItems;
     int mIndex;
    
     public DDImagesButton(DropdownItem[] items) {
      super(items[0], false);
      mItems = items;
      updateIndex(0);
      setChangeListener(this);
     }
    
     protected void paint(Graphics graphics) {
      super.paint(graphics);
    
      int x = mItems[mIndex].mBitmap.getWidth() + 2;
      int y = 5;
    
      int y1 = y;
      int y2 = y + 10;
      int x1 = x;
      int x2 = x + 18;
      int[] xPts = new int[] { x1, x2, x1 + 9 };
      int[] yPts = new int[] { y1, y1, y2 };
      graphics.drawFilledPath(xPts, yPts, null, null);
     }
    
     public void fieldChanged(Field field, int context) {
      getScreen().getUiEngine().pushScreen(new DDImagesPopUp());
     }
    
     public void updateIndex(int index) {
      mIndex = index;
      mItem = mItems[mIndex];
      mWidth = mItem.mBitmap.getWidth() + 6 + 18 + 3;
      mHeight = mItem.mBitmap.getHeight() + 6;
      invalidate();
     }
    
     class DDImagesPopUp extends PopupScreen implements FieldChangeListener {
    
      public DDImagesPopUp() {
       super(
         new VerticalFieldManager(VERTICAL_SCROLL
           | VERTICAL_SCROLLBAR));
       for (int i = 0; i < mItems.length; i++) {
        BitmapButtonField button = new BitmapButtonField(mItems[i],
          true);
        add(button);
        button.setChangeListener(this);
       }
       setFieldWithFocus(getField(mIndex));
      }
    
    protected boolean keyChar(char key, int status, int time) {
        if (Keypad.KEY_ESCAPE == key) {
            this.close();
            return true;
        } else
            return super.keyChar(key, status, time);
    }
    
      public void fieldChanged(Field field, int context) {
       updateIndex(getFieldWithFocusIndex());
       close();
      }
     }
    }
    

    Sample of use:

    class Scr extends MainScreen {
     DDImagesButton ddImages1;
     DDImagesButton ddImages2;
    
     public Scr() {
      HorizontalFieldManager hfm = new HorizontalFieldManager();
      add(hfm);
    
      DropdownItem[] items = new DropdownItem[6];
      items[0] = new DropdownItem(Bitmap.getBitmapResource("1.png"),
        "Add Item");
      items[1] = new DropdownItem(Bitmap.getBitmapResource("2.png"),
        "Attachment");
      items[2] = new DropdownItem(Bitmap.getBitmapResource("3.png"), "Time");
      items[3] = new DropdownItem(Bitmap.getBitmapResource("4.png"), "User");
      items[4] = new DropdownItem(Bitmap.getBitmapResource("5.png"), "Group");
      items[5] = new DropdownItem(Bitmap.getBitmapResource("6.png"),
        "Information");
      ddImages1 = new DDImagesButton(items);
      hfm.add(ddImages1);
    
      ddImages2 = new DDImagesButton(items);
      hfm.add(ddImages2);
     }
    }