User Interface (UI)

Overview

This document describes how to create UIs for BlackBerry device applications. For more information, see the following sections:

UI frameworks

You can create UIs for the BlackBerry device using the following frameworks: BlackBerry UI APIs, Mobile Information Device Profile APIs, and Scalable Vector Graphics APIs.

BlackBerry UI APIs

Packages: net.rim.device.api.ui, net.rim.device.api.ui.autotext, net.rim.device.api.ui.component, net.rim.device.api.ui.container, net.rim.device.api.ui.decor, net.rim.device.api.ui.text, net.rim.blackberry.api.spellcheck, net.rim.device.api.browser.field, net.rim.device.api.lbs

To create UI applications that are optimized to run on the BlackBerry platform, as well as interact efficiently with core device applications (such as mail, phone, and browser applications), use the BlackBerry UI APIs. For a detailed overview on the BlackBerry UI APIs, see the package overview.

Applications using the BlackBerry UI APIs are not portable to other mobile devices.

Mobile Information Device Profile (MIDP) APIs

Packages: javax.microedition.lcdui, javax.microedition.lcdui.game, javax.microedition.midlet

MIDlets are applications that use only the standard Mobile Information Device Profile (MIDP) APIs and Connected Limited Device Configuration (CLDC) APIs. The Blackberry currently supports both MIDP version 1.0 (JSR 37) and 2.0 (JSR 118). MIDlets run on BlackBerry® devices and other devices that support the Java™ Micro Edition (Java ME) platform.

For a detailed overview on the MIDP UI APIs, see the package overview.

Scalable Vector Graphics (SVG)

Packages: org.w3c.dom, org.w3c.dom.events, org.w3c.dom.svg , net.rim.plazmic.mediaengine , net.rim.plazmic.mediaengine.io

SVG is a text-based markup language similar to HTML that represents 2D vector graphics, animation, and interactivity. SVG support was added to J2ME with JSR 226. Vector graphics rely on geometrical primitive objects such as lines, circles, polygons. Since they are based on geometry, vector graphics can be easily manipulated without loss of accuracy. When developing for mobile devices, SVG has the advantage of automatically scaling to the screen resolution on the device. In addition, you can use SVG for both MIDlets and BlackBerry API applications.

There are two ways to use SVG in your applications on a BlackBerry device:

Advantages of the BlackBerry API UI framework [back to top]

While you can use either MIDP or BlackBerry UI APIs, consider the following advantages that are available when using the BlackBerry API UI framework to create UIs.

Increased display options

A major difference between the MIDP and BlackBerry API UI frameworks is the number of display options permitted. MIDP separates UI components into high and low-level APIs. When using the high-level APIs to ease portibility between mobile device platforms, only one Displayable object, which represents the device screen, can be viewed at one time. As a result, you can only view certain types of UI components at a time. For example, you cannot combine a List with another type of UI component, such as a Gauge.

In contrast, the BlackBerry UI's Screen object, you can combine any number of field objects together into a Manager, such as a ListField, GaugeField, and numerous BitmapField objects. Certain Displayable objects in MIDP (such as List and Alert) are considered Field components in the BlackBerry UI. In this respect, the BlackBerry UI is more extensible, enabling you to create complex application interfaces more efficiently.

Using Custom Fields

A Field is an object container in the BlackBerry APIs that holds and lays out a particular type of data for display in the UI. The BlackBerry APIs provide a number of useful ways to display particular types of data in a Field, none of which can be embedded into a MIDlet . For example:

In addition to the useful Field types defined in the BlackBerry UI, you can create your own. The BlackBerry UI provides you with the functionality to extend the basic Field to create any type of field.

Click here for a code sample on creating a custom text field that contains (non-editable) separate pieces of text.

class MultiElementTextField extends Field {  //  we must extend field
   String[] _texts; // an array of text segments
   int[] _spaces; // an array containing the amount of space
                       // allocated to each text segment
   int_buffer; // an integer value which represents
                       // the amount of buffer space between
                       // each text segment
   /* Constructor sets up each of the data arrays
      and the buffer value */
   public MultiElementTextField(Object[] data, int buffer, long style)
       throws IllegalArgumentException {
       super(style); // a call to super, this sets up the
                       // particular style of the field.
       int n = data.length;
       if ((n % 2) != 0) {
          throw new IllegalArgumentException("Invalid number of elements");
       } else {
           _texts = new String[n / 2];
           _spaces = new int[n / 2];
       }
       for (int i = 0; i < n ; i = i + 2) {
           _texts[i / 2] = (String)data[i];
           _spaces[i / 2] = ((Integer)data[i+1]).intValue();
       }
       _buffer = buffer;
   }
   public boolean isFocusable() {
       // this field can accept the focus, return true
       return true;
   }
   /* we use layout to determine the extent of the field,
      we ultimately call setExtent(int, int) with the total field size */
   public void layout(int width, int height) {
       Font font = getFont();
       int _fieldHeight = font.getHeight();
       int _fieldWidth = 0;
       int n = _spaces.length;
       for (int i = 0; i < n; ++i) {
          _fieldWidth += _spaces[i];
           if (i < n - 1) {
               _fieldWidth += _buffer;
           }
       }
       setExtent(_fieldWidth, _fieldHeight);
   }
   /* paint draws the text objects to the screen using the
      graphics object passed in. Here we are using the values
      from buffer and spaces[] to determine the location and
      size of each segment of text.We use the ELLIPSIS style
      to handle text that is too long for its allocated space
      by replacing any characters that do not fit with ... */
   public void paint(Graphics graphics) {
       int xpos = 0;
       int n = _spaces.length;
       for (int i = 0; i < n; ++i) {
           graphics.drawText(_texts[i],xpos,0,graphics.ELLIPSIS,_spaces[i]);
           xpos += _spaces[i];
           if (i < n - 1) {
               xpos += _buffer;
           }
       }
   }

To create similar objects using the MIDP APIs, you can use the CustomItem class. However, unlike Field extensions, this approach does not allow you to easily modify display options such as borders, layout, and theming.

Controlling layout

The BlackBerry API provides layout managers that offer flexibility in displaying Fields. You declare a layout manager at the top level of your screen, and then add field components to it. Since layout managers are types of Field, they can be embedded in other layout managers.

Click here for a code sample on creating a custom layout for a Screen.

class LayoutManager extends Manager {
   public LayoutManager() {
       //construct a manager with vertical scrolling
       super(Manager.VERTICAL_SCROLL);
   }
   //overwrite the nextFocus method for custom navigation
   protected int nextFocus(int direction, boolean alt) {
       //retrieve the index of the current field that is selected
       int index= this.getFieldWithFocusIndex();
       if(alt) {
           if(direction 0){...}
               else{...}
       }
      // if we did not handle it, let the manager's parent class
      if (index == this.getFieldWithFocusIndex())
          return super.nextFocus(direction, alt);
      else
          return index;
   }
   protected void sublayout(int width, int height) {
       Field field;
       //get total number of fields within this manager
       int numberOfFields = getFieldCount();
       int x = 0;
       int y = 0;
       for (int i = 0;i < numberOfFields;i++) {
           field = getField(i); //get the field
           setPositionChild(field,x,y); //set the position for the field
           layoutChild(field, width, height); //lay out the field
           y += ...;
           ...
       }
       setExtent(width, height);
   }
   public int getPreferredWidth() {
       return 160;
   }
   public int getPreferredHeight() {
       int height= 0;
       int numberOfFields= getFieldCount();
       for (int i= 0; i < numberOfFields; i++) {
           height+= getField(i).getPreferredHeight();
           return height;
       }
   }
   /****************
    Main Class
   ****************/
   ...
   RichTextField myField = new RichTextField("Hello");
   RichTextField myOtherField = new RichTextField("World");
   LayoutManager myManager = new LayoutManager();
   MainScreen myScreen = new MainScreen();
   myScreen.add(myManager);
   myManager.add(myField);
   myManager.add(myOtherField);

The closest relation to a layout manager in the MIDP API is Form. It vertically aggregates Item objects on the display, but does not allow you to change the order in which the items are displayed. As a result, if your interface requires a specific ordering, involves frequent scrolling between fields or a horizontal field layout, BlackBerry API layout managers are more suitable.

Alerting using PopUpScreens

The BlackBerry UI has two main types of Screen objects: PopupScreen, which is subclassed by Dialog and Status, and FullScreen, which is subclassed by MainScreen.

You can use the BlackBerry UI to display information that is supplementary to your application in a pop-up screen without interrupting the flow of the application. As a result, you do not have to leave the main screen, and then return to it later. In addition, you can prioritize which PopupScreen objects get pushed to the top of the display stack using pushGlobalScreen(Screen, int, int).

Because MIDP is intended for devices with minimal displays, such as mobile phones, Alert object functions differently from PopupScreen in the BlackBerry APIs. Alert objects are Screens that use the entire display when they are invoked.

Creating Menus

The MIDP UI prioritizes commands according to the device specifications, and assigns certain commands to soft keys (non-hard-coded keys on the mobile device). BlackBerry devices organize commands on a menu that is accessible by clicking the trackwheel/trackball. You can specify the order of menu items and the menu item that is selected by default when the menu opens. In addition, you can add or remove menu items depending on the screen or application state when the menu displays.

Using Listeners

The MIDP UI includes one default type of listener, CommandListener. You can only register one CommandListener for each Displayable object. After you register a CommandListener with the Displayable object, you can write code to perform an action when that object is selected. For example, you can assign a command listener to a Form, and then perform an action when the user selects an item in the Form. The MIDP UI also contains functions for basic event handling that is based on keyboard input.

The BlackBerry UI offers a flexible implementation of listeners, based on the more involved level of components that can be structured on a screen. The BlackBerry UI contains a generic event listener model that enables you to implement listeners for many types of events, such as when a user presses a key or clicks the trackwheel/trackball, or field, focus, and scrolling changes.

Handling interactions between MIDlets and BlackBerry Java applications [back to top]

When you create UI applications using MIDlets, you can invoke a variety of BlackBerry APIs to provide specific functionality only available for BlackBerry Java applications. For example, if your MIDlet UI application requires the ability to notify users when specific events take place, it can invoke the methods available in the net.rim.device.api.notification package. As a result, however, this makes your application not portable to other mobile devices.

Most BlackBerry Java application classes can be invoked from MIDlet UI applications. However, do not attempt to use any classes in the net.rim.device.api.ui package. Doing so is unsupported, and, due to potential incompatibility with future BlackBerry handheld software releases, may result an unpredictable user experience.

Managing UI application threads [back to top]

All UI applications written using the BlackBerry UI framework contain one event dispatcher thread, which you invoke using Application.enterEventDispatcher(). After a Screen object is pushed onto the display stack, make all modifications either on the event dispatcher thread, or on a background thread while holding the event lock. This is for performance reasons and to avoid concurrency issues; attempting to make changes using a non-thread not synchronized on the event lock throws RuntimeException.

Using a background thread with the Event Lock [back to top]

Use background threads to access the UI by acquiring the event lock for a short time, without interfering with processing by the event dispatcher. Invoke Application.getEventLock() on the background thread to retrieve the event lock, and then synchronize this object to serialize access to the UI. You should only hold this lock for short periods of time because the event dispatcher thread is paused. An application should never call notify() or wait() on this object.

For example, in a timer task, you could write code in the following method:

Click here for a code sample on acquiring an event lock.

class MyTimerTask extends TimerTask {
   public void run() {
       synchronized(Application.getEventLock()) {
           _label.setText("new text " + System.currentTimeMillis());
       }
   }
}

Using the Event Dispatcher Thread [back to top]

To use the event dispatcher thread on all Fields on the display stack, create a class that implements the Runnable interface. You can then invoke its run() method on the event dispatcher thread using one of the following methods (each found in net.rim.device.api.system.Application):

Before a Field or Screen is added or after it is removed (popped-off) from the display stack, any thread can modify the Screen object.

Click here for a code sample for invoking invokeLater(Runnable runnable) to update a screen on the event thread.

UiApplication.getUiApplication().invokeLater (new  Runnable() {
    public void run()
    {
        //Perform screen changes here.

        //Calling invalidate() on your screen forces the paint
        //method to be called.
        screenName.invalidate();
    }
});

Using Modal Screens [back to top]

Screen objects are pushed to the display stack using the pushScreen() and pushModalScreen() methods of the UiApplication class. Because pushModalScreen() blocks until the screen is removed from the display stack (where pushScreen() returns immediately), the order of operations is crucial when you use modal screens. Do not invoke pushModalScreen() before starting the event dispatcher thread; doing so throws RuntimeException. Note that other methods, such as Dialog.inform and Dialog.alert from Dialog class, also use pushModalScreen().

The following code sample shows how to properly display a modal and non-modal screen in an efficient manner.

Click here for a code sample on efficiently displaying a modal and non-modal screen.

public class MyApp extends UiApplication implements Runnable {
    public MyApp() {
        MainScreen screen = new MainScreen();
        screen.setTitle("My Application");
        screen.add(new LabelField("Welcome to my application!"));
        this.pushScreen(screen);
    }
    public static void main(String[] args) {
        MyApp app = new MyApp();
        new Thread(app).start();
        app.enterEventDispatcher();
    }
    public void run() {
        while (! this.hasEventThread()) {
            Thread.yield();
        }
        this.invokeAndWait(new Runnable() {
            public void run() {
                Dialog.inform("This dialog is being displayed");
            }
        });
    }
}		

Copyright 1999-2008 Research In Motion Limited. 295 Phillip Street, Waterloo, Ontario, Canada, N2L 3W8. All Rights Reserved.
Copyright 1993-2003 Sun Microsystems, Inc. 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
Copyright 2002-2003 Nokia Corporation All Rights Reserved.
Java is a trademark or registered trademark of Sun Microsystems, Inc. in the US and other countries.