Question

Le champ ObjectChoiceField répond à toutes mes exigences mais il n’est pas beau.

Voici ce que j'ai:

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

Mais je préférerais avoir des images dans la liste déroulante. D'après ce que j'ai compris, le tableau d'objets doit contenir des objets prenant en charge la méthode toString. Il doit y avoir un moyen de le faire, je le vois dans d'autres applications, je ne trouve pas le bon objet dans l'API.

Il n'est pas nécessaire que ce soit un ObjectChoiceField.

Était-ce utile?

La solution

J'utiliserais les champs personnalisés ButtonField et PopupScreen. Deux raisons:

  • dans la conception mobile, il est préférable d’utiliser efficacement l’écran, et le contrôle du menu déroulant classique du bureau semble moins suffisant que le menu contextuel, du moins pour les éléments complexes (image + texte)
  • c'est plus simple :)

texte de remplacement 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;
 }
}

Champ de bouton personnalisé:

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

Contrôle déroulant lui-même:

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

Exemple d'utilisation:

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

Autres conseils

Je ne connais pas bien le développement de Blackberry, mais je suppose que vous pouvez sous-classer ObjectChoiceField et écraser les méthodes layout(int, int) et paint(Graphics).

Et ensuite, dans drawImage(...), utilisez peut-être la méthode <=> de l'objet Graphics transmis pour dessiner l'image.

Juste une conjecture

Ma réponse va dans le sens de réponse de jitter . L’idée générale du type de personnalisation que vous souhaitez est de remplacer le comportement par défaut des composants de base.

Supposons que les choix que vous souhaitez afficher puissent être encapsulés par une classe nommée Choice déclarée comme suit:

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

vous pouvez alors déclarer une instance ObjectListField en tant que:

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

définissez les éléments de votre choix comme suit:

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

puis ajoutez-le à votre Screen (ou FieldManager de votre choix) à l'aide de:

add(choice);

Je n'ai pas pu remplacer les éléments du menu contextuel de la sélection actuelle. Cela semble appeler la méthode toString() des éléments de votre choix. C’est pourquoi j’ai annulé l’implémentation par défaut de <=> dans la classe <=> afin que nous puissions afficher les noms logiques dans cette fenêtre contextuelle.

S'il s'agit d'un widget java, il est fort probable que vous puissiez passer du code HTML simple en tant qu'éléments à afficher dans le champ de choix (ou que toString () renvoie un code HTML simple). Ensuite, si c'est le cas et que vous passez une URL d'image / un chemin relatif, l'image doit être affichée. Pour autant que je sache, cela fonctionnerait au moins dans Swing, par exemple ...

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

(espaces ajoutés pour que le code apparaisse dans l'aperçu)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top