Pregunta

El campo ObjectChoiceField cumple con todos mis requisitos pero no es bonito.

Esto es lo que tengo:

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

Pero preferiría tener imágenes en el menú desplegable.Tengo entendido que la matriz de objetos debe contener objetos que admitan el método toString.Tiene que haber una manera de hacerlo. Lo veo en otras aplicaciones, simplemente no puedo encontrar el objeto correcto en la API.

No tiene que ser un ObjectChoiceField.

¿Fue útil?

Solución

Usaría ButtonField y PopupScreen personalizados. Dos razones:

  • en el diseño móvil, es mejor usar la pantalla de manera efectiva, y el control desplegable de escritorio clásico parece ser menos suficiente que la ventana emergente, al menos para elementos complejos (imagen + texto)
  • es más fácil :)

texto alternativo 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;
 }
}

Campo de botones personalizado:

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

Control desplegable en sí:

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

Muestra de uso:

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

Otros consejos

No estoy familiarizado con el desarrollo de Blackberry, pero supongo que se podrían crear subclases. ObjectChoiceField y sobrescribir el layout(int, int) y el paint(Graphics) métodos.

Y luego en paint(Graphics) tal vez use el drawImage(...) método del objeto de gráficos pasado para dibujar la imagen.

Sólo una suposición descabellada

Mi respuesta estará en la línea de respuesta de jitter . La idea general para el tipo de personalizaciones que desea es anular el comportamiento predeterminado de los componentes básicos.

Suponga que las opciones que desea mostrar se pueden encapsular mediante una clase llamada Choice declarada de la siguiente manera:

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

entonces puede declarar una ObjectListField instancia como:

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

establezca sus elementos de elección como:

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

y luego agréguelo a su Screen (o FieldManager de su elección) usando:

add(choice);

No he podido anular los elementos del menú emergente de selección real. Esto parece llamar al método toString() de sus elementos de elección. Es por eso que he anulado la implementación predeterminada de <=> en la clase <=> para que podamos mostrar nombres lógicos en esa ventana emergente.

Si se trata de un widget de Java, entonces es probable que pueda pasar html simple como elementos para mostrar en el campo de elección (o que toString () devuelva html simple). Entonces, si ese es el caso y pasa una URL de imagen / ruta relativa, la imagen debería mostrarse. AFAIK que funcionaría en Swing al menos, por ejemplo ...

" < html > Perro & Lt; img src = " dog.png " > < / html > "

(espacios añadidos para que el código se muestre en la vista previa)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top