Creating Custom Fields BLACKBERRY

We’ll create a couple of custom fields, first a simple static noninteractive one to introduce the concepts and then a more complicated one that deals with user interaction, focus, and events.

Adding a Custom Label Field

We’ll start by replacing the Please Enter Your Credentials field with one built from scratch that will use different foreground and background colors and contain a small image. It’s a simple field to make but will illustrate the basic concepts well.

Creating the Basic Field Class

Create a new class under the com.beginningblackberry.uifun package called Custom Label Field that subclasses net.rim.device.api.ui.Field. Here’s the basic outline,with placeholders for the two abstract methods that we’re required to implement for any field:

Bitmap and DrawStyle will be used by the field a bit later; we just added the import statements now for convenience.

Creating a Constructor

We’ll now add a constructor and a few member variables to contain the label text and foreground and background colors (we’ll add the image shortly):

NOTE: Colors on the BlackBerry are represented by ints. You can use one of the constants in the
net.rim.device.api.ui.Color class to select a desired color, or specify a color in hexadecimal RRGGBB format, the same as in HTML, such as 0xFF0000 for red or 0x0000FF for blue. The BlackBerry actually uses a 16-bit color model, with 5 bits for red, 6 for green, and 5 for blue. It’ll automatically select the closest color to whichever one you specify, but it may not appear exactly as on screen,and the apparent color can vary from device to device depending on screen characteristics. So be sure to test out your color choices on a range of real devices. One final thing to notice in the constructor; we’ve added a style parameter so the user of this field can set styles. It’s a good idea when creating fields to provide at least one constructor where style flags can be set.

Adding the layout Method

We’ll do something very simple for the layout method.Since we want our label field to span the width of the screen, we’ll just use the passed-in width parameter as our field width. Remember the width parameter tells how much space is available to our field.We’ll base the height on the height of the Field’s font:

Although it’s a simple method,there’s an important principle illustrated here: Because there are a wide range of BlackBerry models, and default fonts and screen resolutions vary quite a bit, you should avoid specifying absolute sizes wherever possible. Instead, you should specify everything relative to the widths and heights available to you at runtime, including the widths and heights of the fonts being used. This will help a great deal in getting your application to run on a different model of BlackBerry. By doing things this way, we could go back and select a different font for our screen, and we wouldn’t have to change this layout method.

After calling setExtent,the getWidth and getHeight methods in our field will return the values we set; this is how the manager containing this field will now how to lay out our field in relation to all the other fields it manages and how it will know how much space to give the field to paint.

Adding the paint Method

To draw text to the display, we can just use the following:

We don’t have to worry about setting a specific font. The Graphics object will have its font set to the field’s current font, meaning that the font that we set earlier in UiFunMainScreen is already the current font for this graphics object.Now, let’s set the foreground and background colors and make sure we clear the field to the background color before we draw the text:

And that’s almost everything we need to do; in fact, at this point, you can try out the label field with our application.

Trying Out the Label Field

In The UiFunMainScreen constructor, replace this line:

And the application will have a label with a different foreground and background (0x999966 is kind of a dark tan color).

Using our custom label

Using our custom label

Adding an Image

Now, we’ll add the ability to display an image to the left of the text. We’ll create another constructor with a Bitmap parameter, and if this is specified, the Bitmap will be drawn at the left edge of the field, and the text will be shifted over to accommodate it. Let’s start with the additional member variable and the constructor:

We’ll make a small change to the layout method, to handle the case where the image is taller than the font:

And we’ll need to make another small change to the paint method. If we were given a bitmap, we’ll draw it and set the x parameter to drawText to the right of the bitmap. We’re also doing something else here: If the bitmap is taller than the font, we want the text centered vertically. Similarly, if the font is taller, we want the bitmap centered vertically. The algorithm in both cases is the same:

position = (Field height – item height) / 2

That’s a good one to keep at hand; you’ll end up using it often in your user interfaces (or the equivalent for horizontal centering).Our new paint method looks like this:

Graphics.drawBitmap is another good method to get familiar with. Its parameters let you draw part of a bitmap or a full bitmap, and it automatically takes into account image transparency, as you’ll see when we put this new field to use with a partially transparent image.

Trying the new CustomLabelField

We’ll change UiFunMainScreen’s constructor again to use CustomLabelField’s new constructor.We’ll have to add a line to load the bitmap first, and add that bitmap to the project as before. You can get the image we’re using here from this book’s page web site.The new lines for the constructor follow:

And running the application, you’ll see the image and text together, as illustrated in Figure.

The label showing our image

The label showing our image

Tying Up Some Loose Ends

The field works now, and in the end,when you’re building a field for your application, all that matters is that it works where you want it to work. We’ll fill in a couple of details here though, to make our CustomLabelField truly complete, and to illustrate a few additional concepts.

First, there are two methods which you should override but don’t absolutely have to: getPreferredWidth and getPreferredHeight. These are used by some layout managers to help with determining field layout before a given field has had a chance to lay itself out. They let the manager know how much space the field needs ideally. There’s no guarantee the manager will give the field that much space, or even call the methods, but they’re easy to implement for our field, so for completeness, we’ll implement them.getPreferredHeight is just the same algorithm we used in layout:

The getPreferredWidth method is a bit trickier. Since we don’t know the width available, we’ll have to come up with a sensible value; in this case, we’ll use the total width of the text in the field’s font, plus the width of the image (if any):

The Font.getAdvance method ust tells us the width, in pixels, needed to render the given string in that font. Now, we’ll take another look at layout. Two parameters were passed in, but we ignored the height parameter.What if the available height is less than the height we need for the font or image? It turns out the BlackBerry API will let us set a height that’s bigger than the available height but will clip our field when it’s drawn.

Basically our paint method would think it had more space than it actually did, which would definitely lead to some drawing bugs. Given our field and application, it’s unlikely we’ll ever actually run into problems with the available height, but it does come into play with other fields, so let’s modify our layout method to respect the height parameter. We’ll also take this opportunity to eliminate some code replication. Since getPreferredHeight used exactly the same algorithm as layout, we’ll just called getPreferredHeight, and if the height passed to layout is less than that, we’ll cap the size at the smaller height:

Finally, what if our text is wider than the available width? This isn’t unlikely; with a slightly larger font, wider image, or narrower screen, we could run out of room easily. Right now, the text will just cut off wherever the screen ends, even in the middle of a letter.Without getting into anything fancy, like text wrapping, we can use another version of Graphics.drawText that allows us to specify the width available for the text and set a flag to draw an ellipsis (. . .) at the end of our text if it exceeds the given space:

Now, if our label is too long, at least it’ll look a bit better.

The CustomLabelField demonstrating the ellipsis

CustomLabelField demonstrating the ellipsis

Finally, let’s revisit the layout method briefly.We made the field always take up the entire width available to it. What if we didn’t want that behavior? How would the application using the field specify its behavior? Take a look at the field style flags available in the Field class. There’s one called USE_ALL_WIDTH. Let’s alter layout so that our label field only uses the full with of the screen if this flag is specified.The change is simple:

Again, we can use getPreferredWidth, because it already gives us the width of the image (if any) plus the text. Finally, to make sure the label on our login screen still spans the entire width, we’ll make a slight change to UiFunMainScreen’s constructor, to pass in Field. USE_ALL_WIDTH as the style flag:

Congratulations, you’ve created your first custom field! You can take the appearance as far as you want (exploring the Graphics class may give you some ideas), but you understand the basics of building a field, except for one crucial piece: how to interact with the user.To illustrate that, we’ll replace our application’s buttons with something a bit different and learn how to create fields that a user can interact with.

Creating a Custom Button Field

To create our new buttons, we’ll again start from scratch. Because you just worked through the basics of drawing a field, we’ll focus only on areas that are different when creating an interactive field.

Laying Out the Interface

We’ll start with the parts that you already know—the layout and paint methods. In this case, we want a size that’s a bit bigger than our text, because we’re going to draw a background for the button that extends beyond the text by a few pixels. We also want to leave one pixel of blank space around the outside of the button, so the two buttons appear well spaced when they’re next to each other on the screen. Figure illustrates the horizontal sizing of the button relative to the text; the vertical layout is similar.

The horizontal dimensions of the custom button field

horizontal dimensions of the custom button field

So, for the layout method, we just add 8 pixels (4 on each side) to the font advance for our button’s text, and add 8 to the font height to get the field’s size. Create a new class called CustomButtonField; the initial code should look like the following:

Painting the Buttons

Instead of clearing the whole field to the background color, we’ll just draw a rounded rectangle of the given background color, and draw the text on top of that. We’ll have to come back to paint when we make this field focusable, but for now, to get something on screen, our paint method looks like this:

Taking a Look

Replace the ButtonFields in UiFunMainScreen with CustomButtonFields, and you’ll see how the buttons look so far. In UiFunMainScreen’s constructor, change the class for the button declaractions from ButtonField to Custom Button Field:

Then, in UiFunMainScreen’s constructor replace the following lines:

with these lines:

Running the application, you’ll see, as you should expect by now, our buttons drawn to the screen as illustrated in Figure.

Two buttons, rounded rectangles with text – no surprises

Two buttons, rounded rectangles with text – no surprises

If you try to use the application now, however, you’ll notice a big difference; you can no longer select the buttons!

Making the Button Focusable

Because most BlackBerry devices use a trackball as their navigation method, the concept of focus is very important. The field with focus is the one that receives events from the user interface and has the first chance to respond to them. (Even the BlackBerry Storm preserves the notion of focus, though having focus is not as critical. When you lightly tap the screen on top of a field, it receives focus.) o make the button focusable we’ll just override isFocusable in CustomButtonField to return true:

Now, you’ll be able to move the focus down to the buttons, but the visual representation shown in Figure is not what we want.

Custom button fields with the default focus drawing behavior

Custom button fields with the default focus drawing behavior

Drawing the Focus

The default focus behavior for the BlackBerry is to invert pixels that are in the background color. This look is fine for many types of fields, but for our button field, we want to change the button to a color that the user specifies at instantiation time.First, let’s add a couple of member variables, so we can specify the color of the focused button’s text and background:

Now, we’ll disable the default focus behavior so that blue rectangle isn’t drawn. To do this, we just override drawFocus and have it do nothing:

Field has a method called isFocus that lets us determine if the field is in focus while we’re painting. We’ll make use of this in our paint method to draw the button in different colors when it’s in focus. To illustrate a little bit more about drawing using the Graphics object, we’re also going to add a shine effect to our focused button by drawing a semitransparent white rounded rectangle on top of the button background:

Transparency is specified through the setGlobalAlpha method on the graphics object. It takes an int that can range from 0 for fully transparent to 255 for fully opaque and affects all subsequent drawing operations with that Graphics object, so be sure to reset the alpha value to 255 before the end of your paint method, or you may see some strange effects in your application. Finally, we need to have the button repaint when its focus state changes.This does not happen automatically, so we need to override onFocus and onUnfocus to explicitly invalidate the field.Be sure to call the superclass’s versions of these methods to maintain the focus behavior:

Changing the button initialization in UiFunMainScreen’s constructor, we’ll specify a green and yellow color scheme for our buttons they have focus:

Custom focus appearance.

Custom focus appearance.

Now, we have buttons that look as we want them to when focused, but when we click them, nothing happens. The final piece to put in place is to have each trackball or touch screen click fire a field-changed event.

Handling Events

Fortunately, the API makes event handling very easy. All we have to do is override navigationClick and call fieldChangeNotify. The API takes care of handling the listener and calling its fieldChanged method:

The status parameter is unimportant for our purposes, but comparing it against values defined in
net.rim.device.api.system.KeypadListener would let us determine if the Alt, Shift, or other keys were being pressed while the user clicked our field. Returning true from this method lets the framework know that we handled this event, so no one else should respond to it. Finally, the BlackBerry ButtonField also fires an event when the user presses the Enter key while the field has focus. We’ll implement that behavior by overriding keyChar:

The Enter key is the only one this field should handle, so we fire a field changed event and return true if that’s the case. Otherwise, we call the superclass’s method that will allow other interested components to handle this keypress if they want. Trying it out, we’ll get the same results as with the BlackBerry ButtonField class.

The fully functional CustomButtonField

The fully functional CustomButtonField

Now we’ve got a fully customized button field that acts like a built-in ButtonField.

A Review of Custom Fields

You can extend the concepts here to make your buttons include images, have different fonts, or anything else your application requires. The same concepts will also let you create many different types of fields. Remember, when implementing a field from scratch you should be concerned with these methods:

  • paint
  • Layout

And when creating an interactive field, you should override at least these methods as well:

  • sFocusable
  • onFocus
  • onUnfocus
  • drawFocus
  • navigationClick
  • keyChar

All rights reserved © 2018 Wisdom IT Services India Pvt. Ltd Protection Status