2013-05-15 3 views
1

J'ai un ImageButton dans un VerticalFieldManager et un VFM dans un HorizontalFieldManager. L'événement clic ImageButton est déclenché lorsque je clique n'importe où dans le champ environnant. Je veux que cet événement de clic ne se déclenche que lorsque vous cliquez sur le bouton ImageButton, et non sur le champ (VFM ou HFM).Blackberry Click Events

Voici le code:

ImageButton Login = new ImageButton(configModel.getLoginButton(), FOCUSABLE|Field.FIELD_RIGHT, "login.png", "plogin.png",0x9cbe95); 
HorizontalFieldManager hfm = new HorizontalFieldManager(USE_ALL_WIDTH); 
VerticalFieldManager loginButtonVfm = new VerticalFieldManager(USE_ALL_WIDTH); 

loginButtonVfm.add(Login); 
hfm.add(loginButtonVfm); 
add(hfm); 


FieldChangeListener loginListener = new FieldChangeListener() { 
public void fieldChanged(Field field, int context) { 
    Dialog.alert("Fired"); 
    } 
} 
Login.setChangeListener(loginListener); 

ImageButton Code de classe est ici:

public class ImageButton extends Field{ 

     //Image Button Class 
     private String _label; 
     private int _labelHeight; 
     private int _labelWidth; 
     private Font _font; 

     private Bitmap _currentPicture; 
     private Bitmap _onPicture; 
     private Bitmap _offPicture; 
     int color; 

     public ImageButton(String text, long style ,String img, String img_hvr, int color){ 
      super(style); 

      _offPicture = Bitmap.getBitmapResource(img); 
      _onPicture = Bitmap.getBitmapResource(img_hvr); 

      _font = Font.getDefault().derive(Font.BOLD, 7, Ui.UNITS_pt); 
      _label = text; 


      _labelHeight = _onPicture.getHeight(); 
      _labelWidth = _onPicture.getWidth(); 

      this.color = color; 

      _currentPicture = _offPicture; 
     } 
     public void setImage(String img){ 

      _offPicture = Bitmap.getBitmapResource(img); 
      _currentPicture = _offPicture; 
     } 

     /** 
     * @return The text on the button 
     */ 
     public void setText(String text){ 
      _label = text; 
     } 
      String getText(){ 
      return _label; 
     } 

     /** 
     * Field implementation. 
     * @see net.rim.device.api.ui.Field#getPreferredHeight() 
     */ 
     public int getPreferredHeight(){ 
      return _labelHeight; 
     } 
     /** 
     * Field implementation. 
     * @see net.rim.device.api.ui.Field#getPreferredWidth() 
     */ 
     public int getPreferredWidth(){ 
      return _labelWidth; 
     } 

     /** 
     * Field implementation. Changes the picture when focus is gained. 
     * @see net.rim.device.api.ui.Field#onFocus(int) 
     */ 
     protected void onFocus(int direction) { 

      _currentPicture = _onPicture; 
      // invalidate(); 
      super.onFocus(direction); 
     } 

     /** 
     * Field implementation. Changes picture back when focus is lost. 
     * @see net.rim.device.api.ui.Field#onUnfocus() 
     */ 
     protected void onUnfocus() { 
      _currentPicture = _offPicture; 
      invalidate(); 
      super.onUnfocus(); 
     } 

     /** 
     * Field implementation. 
     * @see net.rim.device.api.ui.Field#drawFocus(Graphics, boolean) 
     */ 
//  protected void drawFocus(Graphics graphics, boolean on) { 
//   // Do nothing 
//  } 
     protected void drawFocus(Graphics graphics, boolean on) { 
      if (on) { 
        //draw your own custom focus. 
        } 
       } 
     /** 
     * Field implementation. 
     * @see net.rim.device.api.ui.Field#layout(int, int) 
     */ 
     protected void layout(int width, int height) { 
      setExtent(Math.min(width, getPreferredWidth()), 
      Math.min(height, getPreferredHeight())); 
     } 
     /** 
     * Field implementation. 
     * @see net.rim.device.api.ui.Field#paint(Graphics) 
     */ 
     protected void paint(Graphics graphics){  
      // First draw the background colour and picture 
      graphics.setColor(this.color); 
      graphics.fillRect(0, 0, getWidth(), getHeight()); 
      graphics.drawBitmap(0, 0, getWidth(), getHeight(), _currentPicture, 0, 0); 

      // Then draw the text 
      graphics.setColor(Color.WHITE); 
      graphics.setFont(_font); 
      graphics.setFont(graphics.getFont().derive(Font.BOLD)); 
      graphics.drawText(_label, 5,9, 
       (int)(getStyle() & DrawStyle.ELLIPSIS | DrawStyle.VALIGN_MASK | DrawStyle.HALIGN_MASK), 
       getWidth() - 6); 

     } 

     /** 
     * Overridden so that the Event Dispatch thread can catch this event 
     * instead of having it be caught here.. 
     * @see net.rim.device.api.ui.Field#navigationClick(int, int) 
     */ 
     protected boolean navigationClick(int status, int time){ 
      fieldChangeNotify(1); 
      return true; 
     } 
} 

Répondre

1

Ce genre de chose est en fait assez facile de trouver des bugs dans, lorsque vous essayez d'écrire sur commande champs vous-même. (Ce n'est pas votre faute ... BlackBerry Java rend ce genre de choses plus difficile qu'il ne devrait l'être!)

Je pense que la meilleure façon de résoudre ce problème est de réutiliser quelque chose que quelqu'un d'autre a déjà testé. Je recommande la recherche à la bibliothèque BlackBerry Advanced UI, en particulier, ces deux classes:

BaseButtonField

BitmapButtonField

Comme je pense qu'ils font exactement ce dont vous avez besoin. Je crois que le code important que vous devez changer ou ajouter à votre ImageButton classe est la suivante:

protected boolean keyChar(char character, int status, int time) 
{ 
    if(character == Characters.ENTER) { 
     clickButton(); 
     return true; 
    } 
    return super.keyChar(character, status, time); 
} 

protected boolean navigationClick(int status, int time) 
{ 
    if (status != 0) clickButton(); 
    return true;  
} 

protected boolean trackwheelClick(int status, int time) 
{   
    if (status != 0) clickButton();  
    return true; 
} 

protected boolean invokeAction(int action) 
{ 
    switch(action) { 
     case ACTION_INVOKE: { 
      clickButton(); 
      return true; 
     } 
    } 
    return super.invokeAction(action); 
}  

protected boolean touchEvent(TouchEvent message) 
{ 
    int x = message.getX(1); 
    int y = message.getY(1); 
    if(x < 0 || y < 0 || x > getExtent().width || y > getExtent().height) { 
     // Outside the field 
     return false; 
    } 
    switch(message.getEvent()) { 

     case TouchEvent.UNCLICK: 
      clickButton(); 
      return true; 
    } 
    return super.touchEvent(message); 
} 

/** 
* A public way to click this button 
*/ 
public void clickButton() 
{ 
    fieldChangeNotify(0); 
} 

Vous serez alors en mesure d'utiliser un FieldChangeListener exactement comme vous êtes maintenant, mais le bouton d'image n'appeler à moins que le clic se produit sur votre bouton.

Si vous voulez, vous pouvez certainement changer le code ci-dessus pour utiliser

fieldChangeNotify(1); 

si 1 est une valeur contexte significatif pour vous. L'important est d'ajouter les autres méthodes et de changer navigationClick().

+0

Pure awesomeness, quel était le problème si vous pouviez décrire un peu votre solution? –

+2

Si vous voyez ce problème sur un écran ** tactile **, je pense que le problème était l'implémentation manquante de 'touchEvent()'. Si vous regardez ce code, vous verrez qu'il fait une vérification pour s'assurer que le toucher est ** à l'intérieur du bouton, et non à l'extérieur. Vous devriez inclure les autres trucs aussi. Par exemple, 'keyChar()' s'assure qu'un utilisateur peut avoir le focus sur votre bouton, et * cliquez * dessus en appuyant sur ENTER. 'trackwheelClick()' rend la manipulation uniforme pour les périphériques trackwheel, etc. – Nate

+0

@Nate Un problème avec le code ci-dessus est que vous avez traité 'navigationClick' et non' navigationUnClick', alors que dans l'événement tactile, vous gérez UNCLCIK. Cela entraînerait l'appel du clickButton deux fois, une fois pendant le clic puis à nouveau pendant le déclic sur les périphériques tactiles. Je recommande généralement aux gens de ne gérer que 'navigationUnclick()' pour se conformer au comportement de l'interface utilisateur standard. – adwiv