Text input best practices

Virtual keyboards, font sizes and screen size differences can affect text input on different Series 40 and Nokia Asha software platform devices. Here are a set of guidelines to help handle these situations:

TextEditor can degrade gracefully to TextBox

The Nokia TextEditor class first arrived with the X3-02 and similar first generation Series 40 touch and type phones. If you must support Series 40 phones older than SDK 1.0, your Canvas text input need to fall back to a full screen TextBox.

The example below is such a TextBox extension which allows the user to edit and save a URL. With a bit more work, a more attractive alternative could also be built up using a Form. Note that newer keyboard devices, even if they are not touch devices, may support a TextEditor directly in a Canvas.

public final class SettingsForm extends TextBox implements CommandListener {
    private final RSSReader midlet;
    private final Command saveCommand = new Command("Save", Command.OK, 0);
    private final Command backCommand = new Command("Back", Command.BACK, 0);

    public SettingsForm(final RSSReader midlet) {
        super("RSS Feed URL", "", 256, TextField.URL & TextField.NON_PREDICTIVE);
        setInitialInputMode("UCB_BASIC_LATIN");
        this.midlet = midlet;

        addCommand(saveCommand);
        addCommand(backCommand);
        setCommandListener(this);
    }

    public void setUrlValue(String url) {
        setString(url);
    }

    public String getUrlValue() {
        return getString();
    }

    public void commandAction(Command command, Displayable displayable) {

        if (command == saveCommand) {
            try {
                RMSUtils.write("settings", getString().getBytes());
            } catch (RecordStoreFullException ex) {
                Log.e("Cannot write settings", "", ex);
            }
            midlet.switchDisplayable(null, midlet.getList());
            midlet.getList().reload(true);
        } else if (command == backCommand) {
            midlet.switchDisplayable(null, midlet.getList());
        }
    }
}.

Measure the actual font size

Different phones can have fonts of significantly different sizes. Be sure to test that the longest localised strings you have will fit on the smallest screen size and soft keys that you need to support. For this task there is no automatic shortcut, you must observe on an actual device, as the emulators may not show a pixel perfect rendition of what the device will show.

If you use dynamically sized or standard fonts, be sure to construct your UI logic based on the height of the characters on a given phone as in the example painter code below:

for (int i = 0; i < titleLines.size(); i++) {
   g.drawString((String) titleLines.elementAt(i), PADDING, textY, Graphics.LEFT | Graphics.TOP);
   textY = textY + Font.getDefaultFont().getHeight();
}

An example app using this technique:

TouristAttractions uses the system standard fonts and dynamically adjusts the UI logic based on the font size.

Handle touchpad and keyboard events

Text input with a touch UI or physical keypad is handled automatically by standard components such as TextEditor. You must support this for your application to work on the widest variety of phones. If you are creating a keyboard game input or a special purpose input, such as a calculator, you may need to go the extra step to detect the raw key codes in order to enable a great UX (User Experience).

When creating your own keyboard map, note that the keyboard layouts vary depending on the variant software installed on the phone. QWERTY becomes QWERTZ in Germany and AZERTY in France. For example, if you map from QWERTY characters to numeric keypad numbers in your keyboard handler, you can do so for one country, but it is virtually impossible to do so for all firmware variants, as there is no way for your code to detect the keyboard layout. Checking the phone’s current language does not tell us what labels are printed on the physical keys.

Automatically focus the TextEditor

Bring up the virtual keyboard and make the TextEditor on a Canvas current when this is the next logical function for the user on a given screen. On phones with a virtual keyboard, it may be necessary to wait for the user to tap on a TextEditor component before bringing up the keyboard. Keyboard-based phones have the advantage that text input does not reduce the available screen size, so we can automatically enter text input mode and save one tap for the user to enter the edit mode.

public void showNotify() {
	if (!midlet.phoneSupportsCategoryBar()) {
		/*
		 * Throw an event forward on the UI thread
		 * 
		 * SDK 1.0 and 1.1 phones don't use an onscreen keyboard,
	  * so enter edit mode right away so the user can just
	  * start typing
		 */
			PlatformUtils.runOnUiThread(new Runnable() {
				public void run() {
					enableKeyboard();
				}
			});
	}

	super.showNotify();
}