Still on the Road with Duke Blog

Version 2



    GUI Design for Mobile Devices
    General Remarks About MIDP GUI Elements
       Children of theScreen Class
       Item-based GUI Composition
       The Sample Application

    The first part of this series introduced key aspects of the Java 2 Platform, Micro Edition (J2ME) and the J2ME Wireless Toolkit and offered a small sample application as a starting point to MIDlet development. In this installment, I focus on the user interface of MIDP applications. We will have a look at what components are available to the programmer and how they fit together. I demonstrate key techniques of MIDP-centered GUI design with an application called Duke's Diary.

    GUI Design for Mobile Devices

    Programming for mobile devices means facing lots of limitations. Besides technical constraints, some of which I have already mentioned in the first article, the programmer has to deal with limited input facilities and a really tiny screen's worth of real estate. Both have, as we will soon see, great influence on the composition of the user interface of a MIDP program.

    Consider a small diary application. When the user enters text, a new entry is created and added to the diary. He can browse through all entries and jump directly to a certain date to see all texts of that day. How should such a program look like on a mobile gadget? Cell phones usually offer a numeric keypad and a few function keys as their only input devices. They are often operated with one hand. Hence, the user cannot navigate to an arbitrary location on screen to activate or manipulate a GUI element--there is no equivalent to the point-and-click metaphor. This leaves two alternatives to control the program. First, a component may be mapped directly to one of the available function keys. Second, the user must manually switch focus to an element in order to control it. The one in possession of the input focus is highlighted so that it can identified easily, and cycling through all available elements is usually done with two or four of the function keys of the cell phone, possibly some special cursor keys. Consequently, programs should require as few manual focus changes as possible.

    Since the tiny displays do not offer much room for presenting information, program output may have to be divided into several parts or sections. As only one part can be visible at a time, the user needs to navigate through them. There are three ways to achieve this. One is to implement navigation programmatically; the second leaves it to the user by utilizing function keys to browse through the different views of the application. Finally, a menu (which could be activated by a function key) might offer direct access to the sections. Undoubtedly, the first solution is quite smart, as it guides the user through the different stages of input.

    On the other hand, there are situations when a program cannot determine what to do next. The next-previous metaphor can be used when several similar pieces of information have to be displayed, which, for instance, applies to address-book or calendar-like data. In many other situations, the program must wait for the decision of the user. For example, in an action game you may choose to see the high score list, change program settings, resume a saved game, start a new one, or quit. A menu is best suited for such scenarios.

    The idea of programmatical navigation is to ask for the next piece of information as soon as the user has completely filled in all currently required fields or when he leaves the last one. In this cases, an additional "continue with next page" command seems redundant.

    General Remarks About MIDP GUI Elements

    Having covered general design considerations for applications on mobile devices, we turn to actual programming. The following sections introduce important GUI-related classes that all belong to the javax.microedition.lcdui package, unless explicitly stated otherwise.

    As we have seen in the first article, a MIDlet is at any time in one of three states: active, paused, or destroyed, which are reflected by the startApp, pauseApp, anddestroyApp methods. A MIDlet is required to implement each of these. When its startApp method is invoked, it can be sure to have access to the display and the input device(s) of the gadget. These resources are represented by theDisplay class. It is common practice to have something like display = Display.getDisplay(this); within thestartApp() method.

    The user interface of a MIDP application is based onDisplayables, objects with the ability to be put on the display of a device. There can be only oneDisplayable visible at a time. It is activated throughdisplay.setCurrent(). Besides its actual content, aDisplayable may have a title, a set of commands, and a ticker (I'll cover commands and tickers in greater detail later). As Displayable is abstract, we work with one of its subclasses, Canvas or Screen, which represent different approaches to interacting with the user.

    • Canvas is the preferred class when writing applications that need to handle low-level events and to directly issue graphics calls for drawing to the display. This is the case for games, for example. The mechanism used to create output is comparable to AWT and Swing components, which have apaint method that gets a Graphics object. This method does the actual drawing and painting. The same applies to Canvas, which has a paint method, too. There is even a Graphics class that, however, belongs to the javax.microedition.lcdui package. I will coverCanvas-based screen output in the third part of this series.
    • Screen is the parent of all high-level user interface classes. As it is abstract as well, we work with one of its children, Alert,Form, List, or TextBox. We will have at closer look at them in the following section.

    Figure 1 shows how the different GUI classes relate to each other. Classes with a dashed border are abstract, and the ones with a thick border are directly used in MIDlets.

    Figure 1. Inheritance diagram of important gui classes
    Figure 1. Inheritance diagram of important GUI classes

    Children of theScreen Class

    The Alert class is intended to inform the user about errors and other situations that require his attention. It consists of an optional image and a text string. Alertis linked with a timer, which means the information is displayed for some time and removed automatically afterwards. You can, however, set the timer value explicitly. For example,anAlert.setTimeout(Alert.FOREVER); forcesAlert to stay on screen until the user explicitly dismisses it. An alert may have an AlertTypeassociated with it as an indication of its nature.

    The List class can be used for three different purposes. First, it offers exclusive choices, so that only one list item may be selected at time. Second, you can allow the user to make multiple selections. Finally, List can be used to create menus. This mode is referred to as implicit.

    A TextBox allows the user to input and edit text. Its capacity--the number of characters it may contain--can be set explicitly. The implementation checks this limit upon input and when the object is manipulated programmatically. This maximum capacity is, however, not related to the portion of text that is actually displayed on screen. In addition, it is possible to specify a constraint in order to enter, for example, only email addresses, URLs, telephone numbers, or passwords. We will use aTextBox in our diary application.

    Item-based GUI Composition

    Form extends Screen, too. It acts as a container that is able to take further components, which need to extend the abstract Item class. MIDP 1.0 does not provide much influence on how these Items are laid out. What can be controlled, though, is the order in which items are displayed. In theory, you can add as many items to aForm as you like, but please keep in mind what I have said about screen real estate and manual focus changes. So the number of elements per Form should be kept as small as possible. There are several classes that extend Item. Among them are the following.

    • A ChoiceGroup is a list of related elements. These elements may consist of a text string and an additional image. Similar to List, you can specify one of three modes that influence the behavior of a ChoiceGroup.
    • DateField is used to display and enter date and time values. We will use this class in Duke's Diary, too.
    • Gauge is used to represent an integer value graphically. It is controlled through two values, a maximum and a current setting (which is always greater than or equal to zero and at most equal to the specified maximum value). A Gaugecan either operate in interactive ornon-interactive mode. In interactive mode, the user may modify the current value. In non-interactive mode, gauges are typically used as notification or state indicators to inform the user how far a long-term activity has grown.
    • ImageItem represents a reference to an image; for example, a picture in the PNG file format. It may contain a label. This class supports some layout policy, which helps to influence how the item is placed on screen, at least to a certain degree.
    • StringItem is a non-editable text field that may have an additional label. It is ideal for presenting information to the user that has been calculated programmatically or obtained from some external source.
    • TextField, on the other hand, is editable. It is used in a similar way as the TextBox. However, it does not extend Screen, but needs to be put into aForm.

    Many GUI classes allow the programmer to specify alabel or a title. Titles act as headlines forDisplayables, whereas labels describeItems. Though it is of course vital to describe what the user sees on screen, it is important to keep labels and titles as concise as possible. Once again, please keep in mind how valuable screen real estate is.

    The Sample Application

    Having described which classes are used to create a MIDlet GUI, we will look at how they work in a real-world application. I have implemented a small diary program that should run on any Java-enabled device based on the CLDC/MIDP stack. For your convenience, we have put an archive including the executable MIDlet suite and all source files here. Figure 2 shows the application on my Sony Ericsson P800.

    Figure 2. Duke's Diary on a Sony Ericsson P800
    Figure 2. Duke's Diary on a Sony Ericsson P800

    As you can see in Figure 2, the program has a main screen, titled entries, that shows all texts that have been added at a certain date. The date currently on display is shown on a ticker. When new entries are typed, they are automatically appended to the current date, no matter which date is currently visible. Figure 3 shows an emulated phone displaying the Edit entryscreen, which is used to alter existing entries as well as to create new ones.

    Figure 3. The Edit entry screen
    Figure 3. The Edit entry screen

    public DukesDiaryMIDlet() { try { /* * load some images */ dukeImage = Image.createImage("/duke.png"); /* * these commands are used by several screens */ backCommand = new Command("back", Command.BACK, 1); okCommand = new Command("ok", Command.OK, 1); /* * "entries" screen */ entriesScreen = new List("entries", List.IMPLICIT); quitCommand = new Command("Exit", Command.EXIT, 1); aboutCommand = new Command("About", Command.SCREEN, 2); dateCommand = new Command("goto date", Command.SCREEN, 2); newEntryCommand = new Command("new entry", Command.SCREEN, 2); editCommand = new Command("edit", Command.ITEM, 2); deleteCommand = new Command("delete", Command.ITEM, 2); entriesScreen.addCommand(aboutCommand); entriesScreen.addCommand(quitCommand); entriesScreen.addCommand(dateCommand); entriesScreen.addCommand(newEntryCommand); entriesScreen.setCommandListener(this); ticker = new Ticker(""); entriesScreen.setTicker(ticker); /* * "Edit entry" screen */ editEntryScreen = new TextBox("Edit entry", "", 255, TextField.ANY); editEntryScreen.addCommand(backCommand); editEntryScreen.addCommand(okCommand); editEntryScreen.setCommandListener(this); /* * "goto date" screen */ gotoDateScreen = new Form("goto date"); newDate = new DateField("new date", DateField.DATE); gotoDateScreen.append(newDate); gotoDateScreen.addCommand(backCommand); gotoDateScreen.addCommand(okCommand); gotoDateScreen.setCommandListener(this); /* * "About Dukes Diary" screen */ aboutAlert = new Alert("About Dukes Diary", "written 2004 by Thomas K