一般来说,Java ME 让我们能够编写可在支持该平台的众多小型设备中移植的应用程序。虽然基本功能在所有受支持的设备上表现良好,但用户界面仍然是困扰开发者的一个常见问题。由于 javax.microedition.lcdui
(Java ME 中的主要用户界面 API)的本地实现在不同设备上差异非常大,因此我们无法保证应用程序拥有设备无关和统一的界面外观。
不统一的界面外观并非开发人员期待更好解决方案的唯一原因。javax.microedition.lcdui
包所支持的组件和功能无法完全满足现有的用户期望。
在这种情况下,轻量级用户界面工具包(Lightweight User Interface Toolkit ,LWUIT) 的出现是激动人心的。LWUIT 为构建用户界面提供了大量小部件。虽然部分窗口部件也可以在受限配置设备用户界面 (limited Configuration Device UI,lcdui)
下使用,但还有大量新的小部件,这些小部件可以帮助应用程序开发人员在可视状态下设计出与桌面部件类似的用户界面。由 lcdui
提供的组件也得到了功能方面的增强。因此,LWUIT 不仅仅提供了新的组件,其 API 还支持广泛的新功能,包括主题、转换等。
据 LWUIT 设计者称,该 API 的灵感和模型来自 Swing。这句话意味深长。最重要的含义在于,小部件是由 LWUIT 代码呈现的,而不是派生自本机的呈现机制。这就确保了设备无关性和视觉统一性。
采用 Swing 结构意味着绘制部件的代码是定义良好的,并且完全不同于定义其行为的代码。因此可以通过替换呈现代码来实现完全定制的界面外观。
在本文中,我们将介绍上面提到的一些重要特性和功能。LWUIT 概述部分将着重讨论以下几个方面:
- 小部件。
- “基础架构”项,如
Resource
和 UIManager
等。
- 主题和转换等功能。
LWUIT 小部件
图 1. 小部件类层次结构
上图为 LWUIT 中的小部件类层次结构简化图,该图改编自 LWUIT 程序包 中的“Developer's Guide”相关部分。如图所示,小部件的基类是 Component
类。我们可以看到,LWUIT 支持的 lcdui
小部件不仅包括熟悉的 List
、Label
,而且还包括 ComboBox
、Dialog
、TabbedPane
等众多新窗口部件。
容器和窗体
在窗口部件中,Container
是基本的“容纳者”,即 Container
可以容纳包括容器在内的其他组件。容器的嵌套功能可以帮助我们创建复杂而精妙的用户界面。容器内的组件排列由 布局管理器 负责。
Form
是顶部有 标题栏(Title Bar)、底部是 菜单栏(Menu Bar)的容器,标题栏可以写入窗体名称,菜单栏可以写入命令和菜单。两栏之间为内容窗格,该窗格用于放置窗体上的组件。
选项卡窗格
TabbedPane
允许大量部件组放置在同一个空间。每组部件都有一个与之关联的选项卡,用户只能看到与选定选项卡相对应的部件组。默认的选项卡位置在窗格顶部。但是,也可 以将其置于左侧、右侧或者窗格下部。图 2 显示了一个顶部具有选项卡的选项卡窗格,且第一个选项卡处于选中状态。
图 2. 选项卡窗格
对话框
Dialog
是一个“永远处于顶层”的组件。默认情况下,对话框是情景式的 (modal),在销毁之前它将阻塞调用线程。对话框共有以下 5 种类型:
Alarm
Confirmation
Error
Info
Warning
对话框可用于向用户传递运行时信息,以及收集用户反馈。不同类型的对话框在显示时将会有相应的提示音。可以向对话框中加入图标,以图形方式指示其类型。图 3 显示了一个带有 OK 和 Cancel 命令的简单警告对话框。
图 3. OK/Cancel 警告对话框
标签和按钮
Label
用于显示图像和文本,但显示内容不能被选中,也不能和用户进行交互。可通过许多对齐功能来精确放置标签和标签上图像的相关文本。
Button
类扩展自 Label
类。按钮有自己的 状态,当它被选中和单击时会生成一个 操作事件。与 Label(
Button 的超类)相似,Button
可以有描述性文本、图像,或二者兼而有之。按钮的三种状态如下:
Rollover
:这通常相当于按钮处于选中状态,获得焦点。
Pressed
:当按钮被单击或按下时。
Default
:当按钮既未被选中,也未被单击时。
Button 类有两个子类:RadioButton
和 CheckBox
。RadioButton
具有 Button 类的全部功能。此外,Radiobutton 可以被添加到 ButtonGroup
中,ButtonGroup 类允许它在组内保持独占选定状态。在按钮组内,某一时刻只能有一个单选按钮处于按下状态。如果另一个按钮被单击,先前处于按下状态的按钮将会被取消选定。同时也要注意,一旦某个单选按钮处于按下状态,再单击该按钮则不会改变其状态。
CheckBox
和单选框的相似之处在于,在它被单击选中的情况下可以记住自身状态。不过,重复单击复选框将会使其在选中和未选中两种状态之间切换。另一个不同之处在于,复选框不能是按钮组的一部分。
图 4 显示了许多按钮,单选按钮和复选框。从屏幕快照中可以看到,前两个按钮处于 default
状态,而第三个按钮处于 rollover
状态。两个复选框都处于 选中 状态,但每组中都只有一个单选按钮处于 选中 状态。
图 4. 按钮、单选按钮和检查框
文本域
TextArea
是显示可编辑文本的组件。可使用本机系统编辑器对其进行编辑,这通常会打开一个新的屏幕。文本域与 lcdui
的 TextField
一样,使用了 约束 的概念。图 5 显示了一个含有文本域的窗体。
图 5. 窗体中的文本域
List
List
是一个广泛使用的组件,它可以向用户传递大量信息项。各信息项以单列形式展现,但每项可以包含多行文本和图像。由于 LWUIT 采用了 模型-视图-控制器 体系结构,因此可以让列表以我们期望的形式显示。列表的数据结构由 ListModel
接口表示。所以列表不会局限于特定数据结构,它可以显示任何实现了该接口对象的信息。同样,列表的呈现由实现 ListCellRenderer
的类来完成,因此,开发人员可以创建各种类型的外观。库中包含上述界面的默认实现,这使得实例化列表非常容易。
图 6. 仅含文本的简单列表
图 6 显示了一个含有 4 个项的简单列表。将其与图 7 中的列表进行对比可以发现,二者外观显示差别较大。图 7 背后的应用程序实现了开发人员的设想,界面美观且极具吸引力。
图 7. 具有多行文本和图像的列表
组合框
ComboBox
是一种节省空间的组件,单击时会有下拉列表显示。用户可以从列表中选择某项。由于ComboBox
扩展自 List
,您也可以将自定义模型和呈现程序用于组合框。图 8 显示了一个下拉列表中含有 4 个项的组合框。
图 8. 组合框
底层支持元素
LWUIT 整合了大量“底层的”支持元素,这使得实现各种功能成为可能。我们来看一下这些元素及其工作原理。
资源
应用程序经常需要非代码项;例如,在应用程序中用作 Label
图标的图像。LWUIT 允许将这些项打包成资源包。从本质上说,资源包是一种可以载入设备的二进制文件。一个应用程序可以有多个资源文件,而每个文件可以包含相同或不同类型的资源元素。受支持的资源元素类型如下:
各资源元素都可以通过一组适当的 Resources
类的方法提取出来。LWUIT 资源包有一个实用工具,即资源编辑器 (Resource Editor),专门用于编辑资源文件。资源文件也可以通过一组 Ant 任务创建。
布局管理器
LWUIT 将高级布局管理器的强大功能带入了小型设备用户界面的设计。它支持的布局管理器如下:
BorderLayout
BoxLayout
FlowLayout
GridLayout
GroupLayout
这些布局管理器与 AWT 和 Swing 环境中的工作方式相同。图 9 显示了 GridLayout
的一个例子。
图 9. 网格布局
Style
LWUIT 在一个地方提供了一种非常简便的定义组件外观的方法。每个组件有一个与之相关的 Style
对象,有关该组件外观属性都可以在此对象中设定。这些属性包括:
当生成某个组件后,将会构建一个默认的 Style
对象。要修改组件外观,可以随时改变该对象的属性值。可以设置一个 主题(theme) 来同时更新所有的 Style
对象,这样所有的小部件都将显示主题中定义的外观。
Painter
Painter
接口允许您在组件背景上绘制图形。Painter 可用于在一个或一组组件的背景上绘制特定的图案。LWUIT 包提供了两个类来实现此接口:
BackgroundPainter
:根据其自身样式绘制组件背景。
PainterChain
:创建一系列产生图层效果的 Painter,每个 Painter 负责绘制一个元素。
UIManager
LWUIT 的一个重要特性是可从单一位置管理整个应用程序的外观。UIManager
类可以调整应用程序的视觉方面。该组件可以确保每个应用程序只有一个 UIManager
对象。此类的方法可以在所有组件上应用同样的外观,从而动态本地化用户界面。
LookAndFeel
LookAndFeel
是负责应用程序各种呈现方式的接口。通过重写此接口的相应方法,可以完全定制应用程序的外观。LookAndFeel
在 LWUIT 包中的具体实现是 DefaultLookAndFeel
,该类控制默认外观的实际呈现。通过使用 UIManager
的 setLookAndFell
方法,可以插入 LookAndFell
的自定义实现。
功能
LWUIT 真正有趣的方面在于,它可以超越组件本身,提供各种让我们创造复杂精妙用户界面的特性。本节,我们将介绍这些功能。
动画和转换
LWUIT 库支持现有窗体与将要显示的窗体之间的、不同模式的转换实现。这种转换的基本实现是通过 Animation 接口
、Motion
类、Transition
类、CommonTransitions
类和 Transition3D
类的机制来完成的,可以在 com.sun.lwuit.animations
包中找到它们。
Animation
接 口定义了动画类对象。由于所有组件都实现了 Animation
,因而它们都具有动画性。然而,组件必须在父窗体中对其自身进行注册,以便获得动画回调,从而执行动画任务。如要停止这些回调,组件必须明确取消注册自身。
transition
是一个抽象类,该类表示从一个窗体过渡到另一个窗体时的动画。它的两个具体子类如下:
CommonTransitions
:含有实现 Slide
和 Fade
两种通用转换类型的方法。
Transition3D
:执行转换(Cube
、飞入 和 旋转
),要求设备支持 3D 图形。因此,目前并不能保证在所有设备上都工作良好。
Motion
是用来实现运动效果的类。内置的运动类型包括 linear
、spline
和 friction
。可以通过实现 Motion
的子类来实现其他类型的运动效果。
主题
主题为应用程序中的所有可视组件定义了统一的外观。例如,如果您希望应用程序中所有按钮都具有绿色的背景,可以通过在主题中定义一个合适的键-值对来完成。一个主题文件基本上由键-值对列表构成,它们定义了相应的属性。下面是 LWUIT 演示包主题文件的一部分:
Menu.bgColor= 555555
Menu.bgSelectionColor= 555555
Menu.fgColor= ffffff
Menu.fgSelectionColor= 99cc00
Scroll.bgColor= 111111
Scroll.bgSelectionColor= 242627
Scroll.fgColor= AAAA00
Scroll.fgSelectionColor= ffffff
SoftButton.bgColor= 000000
SoftButton.fgColor= ffffff
TextField.bgColor= 242627
TextField.bgSelectionColor= 242627
TextField.fgColor= 99cc00
TextField.fgSelectionColor= ffffff
主题可以被打包到资源文件中。要应用某个主题,必须先使用类 Resource
将其载入。收到的哈希表必须通过必要的操作将其提交至 UIManager
。
正如我们所看到的,每个组件都有与其关联的样式。当主题被设定后,属性值就会从主题数据和样式对象中读取,从而所有相应类型的组件也根据此值进行更新。不过,这些规则也有一个例外:这种修改仅影响那些未被手动修改的属性。此功能允许您有选择地应用主题。
图10. 主题
图 10 显示了有关主题的示例。右下角的鱼出现了动画效果。
其他功能
除主题和动画外,LWUIT 还支持:
- 日志记录:这是一项调试辅助功能,允许您记录运行时信息。
com.sun.lwuit.util.Log
类提供了将日志信息写入 日志 文件(在 root 目录中创建)的方法,也可以在 Form
和控制台上显示日志信息。可以通过 FileConnection
API 来使用保存在日志文件中的信息。
- 3D 图形:在某些移动设备上支持可选的硬件加速,以提高其性能。
结束语
对于 Sun Java (TM) Wireless Toolkit ,LWUIT 运行非常慢。这是某些体系结构问题所致,从 LWUIT Developer's Guide 中不难发现,运行性能问题不会出现在 Sprint Wireless Toolkit version 3.2 或更高版本上(它们具有不同的体系结构。我还没有测试过 Sprint Toolkit,但我将演示程序载入到手机后,它表现良好。这是第一个 LWUIT 发行版,并且可以对其进行扩充。据估计,它将发展成为一个 UI 库,并且已经有了初步进展。它还将在硬件水平不断发展的未来具有极强的生命力。Java ME UI 开发人员现在有望开发出更加令人满意的产品,以满足未来很长一段时间的需求。
参考资料
- Lightweight User Interface Toolkit (LWUIT) 项目主页
- LWUIT 下载包
- Jonathan Knudsen 的 LWUIT 教程