Tuesday, November 3, 2009

Optimized For The Touch

The LWUIT developer guide generally recommends increasing the padding of components to make them "finger friendly" as a generic guide for LWUIT on touch devices. While this is true, its somewhat basic and we can do much more in LWUIT and outside of it to make our application easier for the touch...

Two of the newer features in LWUIT's SVN are touch menus and tactile feedback, both are off by default and should be explicitly activated. The reason for this is that we don't want to "enforce" our opinion on how touch should look/feel on an application.
You can query whether the device supports touch by invoking Display.getInstance().isTouchScreenDevice()

Notice that the isTouchScreenDevice() method doesn't work properly on some simulators... However, it seems to work reasonably well on the actual devices.

To enable touch menus just use:
UIManager.getInstance().getLookAndFeel().setTouchMenus(true);

You can customize the look of the buttons via the "TouchCommand" selector in the theme.

The tactile feedback causes the phone to vibrate when the user presses a component that is intractable (e.g. list/button). Since most touch screens aren't of very good quality this is very useful in giving the user a sense that the screen actually registered his interaction. To enable this you can use:
UIManager.getInstance().getLookAndFeel().setTactileTouchDuration(100);

The argument is the number of milliseconds to vibrate on touch 50 to 100 seem like reasonable numbers, 0 disables the feature.

Component now has isTactileTouch()/setTactileTouch(boolean) methods to toggle the tactile touch vibration per a specific component. By default LWUIT tries to initialize this based on focusability so for custom components it might be useful to manipulate this flag.

A somewhat older flag which we would recommend is fireOnClick() for Lists. By default lists require two clicks to activate an entry, the first selects the entry and the second opens it.
This allows "context command flow", e.g. a command such as "remove" that removes the current selected entry. However, on touch devices this sort of behavior is often inconvenient and you would expect the "remove" command to move you to a separate list of checkboxes to select the entries to remove.
You would normally expect a single tap on the entry to act like the fire key (send an action event immediately) and not like simple selection. Calling List.fireOnClick(true) makes the list behave like that which is more convenient for touch device, however you need to ensure your application flow can handle this.

There is also the virtual keyboard that Chen blogged about recently, this is immensely useful for touch and Chen has improved its performance considerably!

As a side note unrelated to LWUIT, many devices have a "compatibility" mode on by default where keys are placed by the device at the bottom of the touch screen to allow "none-touch" Java ME applications to run on the device. Applications are expected to explicitly declare their support for touch to utilize the full screen of the device. This is done using the following Jad flags:

Navi-Key-Hidden: true
Nokia-MIDlet-On-Screen-Keypad: no
MIDlet-Touch-Support: true

Notice that the last entry (MIDlet-Touch-Support) is required by current/older Samsung/LG devices but is illegal by the MIDP specification hence fails on Nokia etc. so for support on these devices you would need a copy of your JAD (only the jad) with this attribute added.

Update: LG  have added another JAD attribute required to hide the native vkb which you should probably add to all applications:
LGE-MIDlet-Display-Nav-Keypad: no

17 comments:

  1. Excellent progress guys!

    Just to clarify, are you saying that MIDlet-Touch-Support flag should only be set in the JAD file on the Samsung/LG phones and not Nokias etc?

    ReplyDelete
  2. Yes, this is only for the JAD though.

    ReplyDelete
  3. So we have one JAR for all devices but multiple JADs. This is not great, but probably better than nothing :)

    ReplyDelete
  4. Really nice, I like it a lot.

    Just two questions Shai:

    - Can you control the height of the height of the menu? I tried on an HTC touch and it would be perfect if it were a little bit smaller.

    - Do you know how do you disable the "compatibility" flag for the HTC Touch Cruise (should be the same for all the WindowsCE, I think)? I tried the ones you mention and it doesn't hide, i have to double click it everytime i start the app. By the way I defined the attributes on the JAR manifest not the JAD, is there any difference?

    ReplyDelete
  5. Height of the menu can be controlled by overriding showMenuDialog as usual.

    I have no idea about the HTC touch's "compatibility flag", the manifest should generally work although might require multiple jar's.

    ReplyDelete
  6. Very nice
    but how can I change the layout of the menu buttons? when I use it shows the buttons in a boxlayout.x_axis instead of the grid layout shown in the picture.

    Vasilis

    ReplyDelete
  7. @Vasilis: Override createCommandComponent(Vector commands); in Form and do whatever you like.

    ReplyDelete
  8. I'm stuck at svn 679 due to a scrolling issue that breaks my apps that was introduced when the BB scrolling was included at some point after 679 and before 699.

    But, I thought I'd try this anyway and it works fine in the 679 rev.

    Since this is "touch" oriented, do you think the soft buttons for Cancel/Select are even needed?

    Any easy way to turn those off for the touch menus?

    ReplyDelete
  9. For the Instinct HD, you can turn off the compatibility keypad with the following JAD property

    Sprint-Canvas-Keypad: no

    ReplyDelete
  10. Hi everybody!

    Do you know if there's any way to edit the Select/Cancel softbuttons that appear with the menu?? I mean the text, not the style.

    Thanks!

    ReplyDelete
  11. Use the localization to change the text of the select/cancel buttons

    ReplyDelete
  12. Shai where is the localization thing you are referring to? I need to get rid of this Select/Cancel commands that appear after the touch menu is displayed..

    ReplyDelete
  13. Try googling LWUIT l10n. However it will only change the text of these labels not remove them.
    I would like to remove them for the next version of LWUIT.

    ReplyDelete
  14. hi.great work done.i run my application on the LG KM900 but virtual keyboard always show in the application how to hide this.i add the JAD attaribute as you said but it not works

    ReplyDelete
  15. LG seems to have added LGE-MIDlet-Display-Nav-Keypad: no
    I will update the post with that information.

    ReplyDelete
  16. Hi,
    whwn i am running one application on the sun wirleless toolkit it working fine.but i am trying to run same application on nokia sdk 40 devices that shows not supported application and i am getting one exception

    Error preverifying class javax.microedition.m2g.ScalableGraphics
    VERIFIER ERROR javax/microedition/m2g/ScalableGraphics.render(IILjavax/microedition/m2g/ScalableImage;)V:
    Cannot find class com/sun/perseus/model/Viewport.


    can u anyone help me how to resolve this one .i have to upload that application in nokia ovi store.

    thanks in advance.

    ReplyDelete
  17. You need to enable the M3G and other API's for build time in order for the verification phase to pass. They aren't mandatory in runtime though.

    ReplyDelete