Would you like to tell us how we are doing?

You bet No thanks

Sorry about the red box, but we really need you to update your browser. Read this excellent article if you're wondering why we are no longer supporting this browser version. Go to Browse Happy for browser suggestions and how to update.

Custom fields

You can only add custom context menu items and custom layouts to a custom field.

Here's how to create a custom field.

Import the following classes:

  • net.rim.device.api.ui.Field
  • java.lang.String
  • net.rim.device.api.ui.Font
  • java.lang.Math
  • net.rim.device.api.ui.Graphics

Import the net.rim.device.api.ui.DrawStyle interface.

Extend the Field class, or one of its subclasses, implementing the DrawStyle interface to specify the characteristics of the custom field and turn on drawing styles.

public class CustomButtonField extends Field implements DrawStyle {
   public static final int RECTANGLE = 1;
   public static final int TRIANGLE = 2;
   public static final int OCTAGON = 3;
   private String _label;
   private int _shape;
   private Font _font;
   private int _labelHeight;
   private int _labelWidth;
}

Implement constructors to define a label, shape, and style of the custom button.

public CustomButtonField(String label) {
   this(label, RECTANGLE, 0);
}
public CustomButtonField(String label, int shape) {
   this(label, shape, 0);
}
public CustomButtonField(String label, long style) {
   this(label, RECTANGLE, style);
}
public CustomButtonField(String label, int shape, long style) {
   super(style);
   _label = label;
   _shape = shape;
   _font = getFont();
   _labelHeight = _font.getHeight();
   _labelWidth = _font.getAdvance(_label);
}

Implement layout() to specify the arrangement of field data. Perform the most complex calculations in layout() instead of in paint(). The manager of the field invokes layout() to determine how the field arranges its contents in the available space. Invoke Math.min() to return the smaller of the specified width and height, and the preferred width and height of the field. Invoke Field.setExtent(int,int) to set the required dimensions for the field.

protected void layout(int width, int height) {
   _font = getFont();
   _labelHeight = _font.getHeight();
   _labelWidth = _font.getAdvance(_label);
   width = Math.min( width, getPreferredWidth() );
   height = Math.min( height, getPreferredHeight() );
   setExtent( width, height );
}

Implement getPreferredWidth(), using the relative dimensions of the field label to make sure that the label does not exceed the dimensions of the component. Use a switch block to determine the preferred width based on the shape of the custom field. For each type of shape, use an if statement to compare dimensions and determine the preferred width for the custom field.

public int getPreferredWidth() {
   switch(_shape) {
      case TRIANGLE:
	      if (_labelWidth < _labelHeight) {
	         return _labelHeight << 2;
	      } else {
	         return _labelWidth << 1;
	      }            
      case OCTAGON:
	      if (_labelWidth < _labelHeight) {
	         return _labelHeight + 4;
	      } else {
	         return _labelWidth + 8;
	      }
      case RECTANGLE: default:
	      return _labelWidth + 8;
   }
}

Implement getPreferredHeight(), using the relative dimensions of the field label to determine the preferred height. Use a switch block to determine the preferred height based on the shape of the custom field. For each type of shape, use an if statement to compare dimensions and determine the preferred height for the custom field.

public int getPreferredHeight() {
   switch(_shape) {
      case TRIANGLE:
       if (_labelWidth < _labelHeight) {
          return _labelHeight << 1;
       } else {
          return _labelWidth;
       }
      case RECTANGLE:
       return _labelHeight + 4;
       case OCTAGON:
       return getPreferredWidth();
   }
   return 0;
}

Implement paint(). The manager of a field invokes paint() to redraw the field when an area of the field is marked as invalid. Use a switch block to repaint a custom field based on the shape of the custom field. For a field that has a triangle or octagon shape, use the width of the field to calculate the horizontal and vertical position of a lines start point and end point. Invoke graphics.drawLine() and use the start and end points to draw the lines that define the custom field. For a field that has a rectangular shape, invoke graphics.drawRect() and use the width and height of the field to draw the custom field. Invoke graphics.drawText() and use the width of the field to draw a string of text to an area of the field.

protected void paint(Graphics graphics) {
   int textX, textY, textWidth;
   int w = getWidth();
   switch(_shape) {
      case TRIANGLE:
       int h = (w>>1);
       int m = (w>>1)-1;
       graphics.drawLine(0, h-1, m, 0);
       graphics.drawLine(m, 0, w-1, h-1);
       graphics.drawLine(0, h-1, w-1, h-1);
       textWidth = Math.min(_labelWidth,h);
       textX = (w - textWidth) >> 1;
       textY = h >> 1;
       break;
      case OCTAGON:
       int x = 5*w/17;
       int x2 = w-x-1;
       int x3 = w-1;
       graphics.drawLine(0, x, 0, x2);
       graphics.drawLine(x3, x, x3, x2);
       graphics.drawLine(x, 0, x2, 0);
       graphics.drawLine(x, x3, x2, x3);
       graphics.drawLine(0, x, x, 0);
       graphics.drawLine(0, x2, x, x3);
       graphics.drawLine(x2, 0, x3, x);
       graphics.drawLine(x2, x3, x3, x2);
       textWidth = Math.min(_labelWidth, w - 6);
       textX = (w-textWidth) >> 1;
       textY = (w-_labelHeight) >> 1;
       break;
      case RECTANGLE: default:
       graphics.drawRect(0, 0, w, getHeight());
       textX = 4;
       textY = 2;
       textWidth = w - 6;
       break;
   }
   graphics.drawText(
       _label, textX, textY, (int)( getStyle() & DrawStyle.ELLIPSIS
               | DrawStyle.HALIGN_MASK ), textWidth );
}

Implement the Field set() and get() methods. Implement the Field.getLabel(), Field.getShape(), Field.setLabel(String label), and Field.setShape(int shape) methods to return the instance variables of the custom field.

public String getLabel() {
   return _label;
}
public int getShape() {
   return _shape;
}
public void setLabel(String label) {
   _label = label;
   _labelWidth = _font.getAdvance(_label);
   updateLayout();
}
public void setShape(int shape) {
   _shape = shape;
}