Как создать раскрывающийся список, в котором вместо текста пользователю будут отображаться изображения?

StackOverflow https://stackoverflow.com/questions/1601887

Вопрос

Поле ObjectChoiceField отвечает всем моим требованиям, но оно некрасиво.

Вот что у меня есть:

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

Но я бы предпочел иметь фотографии в раскрывающемся списке.Насколько я понимаю, массив объектов должен содержать объекты, поддерживающие метод toString.Должен быть способ сделать это. Я вижу это в других приложениях, но просто не могу найти правильный объект в API.

Это не обязательно должен быть ObjectChoiceField.

Это было полезно?

Решение

Я бы использовал собственные ButtonField и PopupScreen.Две причины:

  • в мобильном дизайне лучше эффективно использовать экран, а классическое раскрывающееся меню на рабочем столе кажется менее достаточным, чем всплывающее окно, по крайней мере, для сложных элементов (изображение + текст).
  • это легче :)

альтернативный текст http://img405.imageshack.us/img405/3746/dropdown.jpg

Дропдаунитем:

class DropdownItem {
 Bitmap mBitmap;
 String mName;

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

Пользовательское поле кнопки:

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

Сам раскрывающийся элемент управления:

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

Пример использования:

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

Другие советы

Я не знаком с разработкой Blackberry, но, думаю, вы можете создать подкласс ObjectChoiceField и перезаписать методы layout(int, int) и paint(Graphics).

А затем в drawImage(...) возможно используйте метод <=> переданного в Graphics-объекта для рисования изображения.

Просто дикая догадка

Мой ответ будет выглядеть так: ответ джиттера . Общая идея для требуемого типа настроек - переопределить поведение основных компонентов по умолчанию.

Предположим, что выбор, который вы хотите отобразить, может быть инкапсулирован классом с именем Choice , объявленным следующим образом:

private class Choice
{
  public Bitmap image;
  public String label;

  public Choice(String name)
  {
    this.image = Bitmap.getBitmapResource(name + ".png");
    this.label = name;
  }

  public String toString()
  {
    return this.label;
  }
}

тогда вы можете объявить ObjectListField экземпляр как:

ObjectChoiceField choice = new ObjectChoiceField()
{      
  protected void paint(Graphics graphics)
  {
    // Get the current selected Choice
    Choice item = (Choice) this.getChoice(getSelectedIndex());

    int xOffset = 5; // 5 px padding on the left
    graphics.drawBitmap(xOffset, 0, 
                        item.image.getWidth(), 
                        item.image.getHeight(), 
                        item.image, 
                        0, 0);
    // Add text after the image and 10px padding.
    xOffset += item.image.getWidth() + 10; 
    graphics.drawText(item.label, xOfffset, 0);
  }            
};

установите элементы выбора как:

choice.setChoices(new Choice[]{ new Choice("choice 1"), new Choice("choice 2")});

, а затем добавьте его в Screen (или FieldManager по вашему выбору), используя:

add(choice);

Мне не удалось переопределить фактические пункты всплывающего меню выбора. Похоже, это вызывает метод toString() по вашему выбору. Вот почему я переопределил реализацию по умолчанию <=> в классе <=> , чтобы мы могли отображать логические имена в этом всплывающем окне.

Если это виджет Java, то, скорее всего, вы можете передать простой HTML в качестве элементов для отображения в поле выбора (или заставить toString() возвращать простой HTML).Тогда, если это так, и вы передаете URL-адрес изображения/относительный путь, изображение должно отображаться.AFAIK, который будет работать, по крайней мере, в Swing, например...

"< html> Собака < img src="dog.png">< /html>"

(добавлены пробелы для отображения кода в предварительном просмотре)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top