Java Solaris 加入Sun中国技术社区 我的社区 注册说明
 
JDK 6.0 API 中文版
 
 
 
 
 
Java API 文档中文版
使用动画转换创建生动的用户体验
 
By Chet Haase, 11/26/07  
内容 编者注:动画转换(Animated Transition)是一个工具库,该主题在 Filthy Rich Clients 一书的第 18 章中有详细的介绍。如 果每个人都购买一本书才能了解这个库,那么这种代价也太大了。因此,本文的目的就是简要介绍这一主题。如果感兴趣,请务必查看 java.net 项目 上的代码, 这本书的网站 上的动画转换演示,或 者甚至可以阅读这本书以了解详细信息。


典型的应用程序生存期由一些状态组成:数据输入表单、结果界面、含有各种图像的相簿、含有项目的购物车等等。通常,应用程序执行繁重的任务使用户在这些不同的界面中切换:新的界面替代原来的表单,突 然在屏幕中弹出结果,图形和 GUI 对象时而从屏幕中跳出。一般而言,各个当前 UI 屏幕都会在操作完成后关闭,然后新的屏幕将取代它的位置。

HTML 应用程序就是一个很好的例子:在某个页面中填写一些数据,单击提交(Submit)按钮,原页面将消除,取而代之的是另一个全新的用户界面。然后,您将仔细审视这个新界面,考 虑自己应该做的事情并找到新的提交按钮。

如果应用程序在这些不同的应用程序状态之间创建一个更具逻辑性的流程,并为用户带来各个新用户界面(UI)会不会更好呢?如果用户不用重新打量各个新用户界面,而是采用应用程序的流程化方式会怎么样呢?< /p>

这正是动画转换的内容:使应用程序用户界面的转换具有动画效果,从而在这些状态之间创建一个无缝的流程。通过帮助用户理解用户界面之间的组合,转换可以帮助保证用户连接到程序。

当然,这个问题对开发人员而言意味着更多的工作。让应用程序消除一个界面并显示下一个界面是处理这种问题的最直观的方法。在界面之间运行某种动画通常要求理解动画过程,然 后编写一大堆自定义代码使界面上的元素具有动画效果。

这正是编写 动画转换 库的原因:从根本上简化应用程序状态之间动画的流程,执行合理的默认动画,以 及让您专注于编写应用程序代码而不是动画代码。

演示时间

我们来看一个简单的演示应用程序 FieldsOfText。该应用程序将模拟一个常见的功能(别处可能也有),用户可以请求 GUI 展开自己并提供更多文本字段。比如说,我将使用一个类似于此的对话框将 至关重要的卡通画 上传到 我的 java.net 博客。应用程序开始只有一个文本字段,但是通过单击 More 或者 Less 按钮可以增加或减少所显示的文本字段数量。

界面底部也有一个提交按钮,因此此类应用程序通常都有提交按钮。此处的按钮实际上并没有执行任何任务,不过它和其他用户界面元素的作用一样,都是显示动画转换的过程。

以下是用于显示 GUI 的代码:

// Add the More/Less buttons container

add(moreOrLess);
// Next, add the proper number of text fields
for (int i = 0; i < numFields; ++i) {
add(textFields[i]);
}
// Finally, add the Submit button at the bottom
add(submitPanel);

在这段代码中, moreOrLess 组件是一个面板,用于保存 More 和 Less 按钮。 textFields[] 数组用于保存将要填充到 GUI 中的各种不同的文本字段。而 numFields 表示我们希望此时显示的数量。 submitPanel 组件是一个面板,用于保存提交按钮。

下面是提供的用户的基本用户界面:

Initial screen of application
图 1. 应用程序的初始界面

当用户单击 More 按钮,原文本字段下面将增加一个文本字段,如下图所示:

Second screen of application, after user clicks More button
图 2. 用户单击 More 按钮之后的应用程序界面

当用户单击 Less 按钮,最下面的文本字段将消失,用户界面将回到图 1。

在典型的应用程序中,上述步骤可能是先消除原始窗口然后再显示新的用户界面。与此不同,动画转换库将平稳地在这些状态之间切换。它将淡入或淡出将要消除或出现的组件(比如说一个文本字段),而 这些组件可能位于不同的位置(如提交按钮)。举例说明,图 3 显示了在前两个界面之间转换时的用户界面:

Animated transition between the first and second screens
图 3. 前两个界面之间的动画转换

在图 3 中,我们可以看到第二个文本字段的淡出效果,而提交按钮将向下移动。

如果要查看动态效果,可以下载我所创建的视频剪辑( QuickTimeMPEG-4 格式)查看转换效果。< /p>

接下来,我们将了解演示应用程序如何实现这种转换效果。

动画转换:API

从最基本的角度而言,这个库由一个 ScreenTransition 对象(负责建立和运行动画)和一个 TransitionTarget 接口(代码需要实现这个接口)组成。

ScreenTransition

建立动画的代码将使用参数创建这个对象。它的构造函数类似以下形式:



public void ScreenTransition(JComponent transitionContainer,
TransitionTarget target,
Animator animator)

此处:

  • transitionContainer 容器的子类将在转换过程中实现动画效果。
  • targetTransitionTarget 的一个实现,它定义了 setupNextScreen() 方法。该方法用于定义转换界面的GUI。
  • animator 定义实际动画的参数,比如说持续时间。关于 Animator 的完整描述不在本文讨论范围之内。有关更多信息,请参阅 参考资料 中的 Timing Gramework 参考指南。

要在应用程序中运行转换,可随时调用 start() 方法:

public void start()

调用此方法时, ScreenTransition 将建立运行转换所需的一切条件,然后将运行转换。

TransitionTarget

TransitionTarget 一是个简单的接口,它只含有一个方法:

public void setupNextScreen()

代码需要实现这个方法并建立转换容器 GUI。这样,当方法完成时,应用程序将处于转换完成时的状态。

API 的使用

接下来,我们来了解一下 FieldsOfText 应用程序是如何使用这个 API 的。

首先,我们建立了一个 Animator 运行后半程的转换动画。我们将在转换起始时刻添加一些加速和减速。这种加速/减速行为并不是必需的,但是一般而言非线性转换的动画效果会好一些( Smooth Moves 这篇文章有详细的解释)。

Animator animator = new Animator(500);

animator.setAcceleration(.2f);
animator.setDeceleration(.2f);

然后,我们建立 ScreenTransition 对象使用主(main) JComponent 对象作为转换的一个容器,以及 TransitionTarget 对象(它实现了 setupNextScreen() 接口)和之前建立的 animator

ScreenTransition transition =

new ScreenTransition(this, this, animator);

当用户单击 More 或 Less 按钮时, actionPerformed() 方法将触发转换:

public void actionPerformed(ActionEvent ae) {

boolean changed = false;
if (ae.getSource().equals(moreButton)) {
if (numFields < MAX_FIELDS) {
numFields++;
changed = true;
}
} else if (ae.getSource().equals(lessButton)) {
if (numFields > 1) {
numFields--;
changed = true;
}
}
if (changed) {
transition.start();
}
}

最后,我们在 setupNextScreen() 方法处理来自 ScreenTransition 的回调:

public void setupNextScreen() {

// First, clear out the previous GUI and start from scratch
removeAll();

// Add the More/Less buttons
add(moreOrLess);
// Next, add the proper number of text fields
for (int i = 0; i < numFields; ++i) {
add(textFields[i]);
}
// Finally, add the Submit button at the bottom
add(submit);
}

注意,这段代码与之前的 GUI 建立代码几乎相同;惟一的不同之处就是首先调用了 removeAll() 消除以前的 GUI。这段代码的全部作用就是为应用程序的合适界面建立 GUI。

就是这样!应用程序还需要一些代码处理其他任务,比如说建立 JFrame、在背景中绘出蓝色的斜线条,以及建立与组件和布局管理有关的一些详细信息。但是应用程序的大部分实际逻辑,特别是与动画转换有关的代码都已经在上面列出了。

那么它是如何工作的呢?

工作原理

当您的代码调用 start() 方法时, ScreenTransition 将计算出转换容器中的组件的当前属性,比如说位置和大小。然后,应用程序将调用 setupNextScreen() 方法,用于建立下一个界面的 GUI。最后,应用程序将计算出刚才建立的界面中的组件的属性。

注意,系统期望转换容器在适当的时候共享组件,而不是使用完全不同的组件表示相同的事物。因此,如果转换前后的两个界面都有一个提交按钮,那么您可能希望在两种情况下都使用相同的 JButton 对象以获得期望的效果。否则,系统将认为前一个按钮消失而新的按钮出现取代它。这并没有特别的技巧;如果希望在界面之间共享组件,那么应该使用在界面中使用相同的组件。< /p>

在这种情况下, ScreenTransition 将含有两个界面中的组件的所有信息:哪个组件在哪个界面中、组件的位置、组件的大小等等。因此,我们便可以计算出两个界面中的组件将发生哪些变化。在 界面之间发生变化的任何组件都将经历以下三种转换之一:

  • 出现:第一个界面没有该组件,而第二个界面含有该组件。
  • 消失:第一个界面含有该组件,而第二个界面没有该组件。
  • 变化:两个界面都有该组件,但是组件将在两个界面之间出现改变。

然后, ScreenTransition 将为各个组件选择合适的转换效果:

  • 出现:组件将在转换过程中淡入显示。
  • 消失:组件将在转换过程中淡出显示。
  • 变化:组件将在转换过程中移动或按比例缩放。

拥有所有这些信息之后, ScreenTransition 将开始运行动画,根据与各个组件相关的转换效果修改该组件的外观。

当转换完成时,控制将返回应用程序。同时,之前应用程序在 setupNextScreen() 中建立的 GUI 将处于活动状态。

自定义效果

应用程序将使用内建的转换效果处理一些常见的情况。通常,淡入淡出和移动/调整大小是组件的默认行为。但是,需要广泛使用动画转换的应用程序可能更希望为特定的组件或在特定的情况下创建自定义效果。比如说,< 您可能希望组件以拉近或拉远的方式消失,或滑出界面。

库中所编写的转换效果是可扩展的。因此,我们可以创建效果并在系统中注册该效果,然后在应用程序中插入自己的效果。这些效果与组件和转换类型相关(出现、消失或变化)。当 ScreenTransition 搜索合适的效果应用于特定的组件和转换类型时,它将使用自定义的效果(如果已注册)。

编写自定义效果其实相当简单:您只需重写两三个方法用于在转换过程中处理建立、消除和绘图之类的功能即可。有关如何编写自定义效果的内容不在本文的讨论范围之内。但是,如果对此特性感兴趣,可以阅读 这本书的网站 上的“第 18 章:动画转换”,其中展示了自定义效果的代码和实例。

小技巧

我们可以在动画转换中使用各种小技巧实现库所需的功能和性能。关于这些技巧的完整介绍,请参阅代码和图书获得详细信息。比如说,动画转换库在转换完成前处理第二个界面的方式就很有趣。还有,动 画转换库处理两个界面中的布局的方式也值得一看。同时,动画转换库还可以在转换过程中快速显示组件的图像快照,从而支持更佳的性能和复杂动画。

未来的工作

动画转换库这个项目还在发展之中。我希望负责该项目的开发人员可以继续重新定义其 API 并增强其功能。与此同时,动画转换库的实用性是毋庸质疑的。它 应该让开发人员能够方便且无缝地连接到不同的应用程序状态,并为他们的用户提供生动的用户体验。

尝试使用动画转换库并将意见发送给我。

参考资料

  • FieldsOfText.java :本文所描述应用程序的完整源代码。
  • Filthy Rich Clients :这本书的网站,该书的第 18 章详细介绍了动画转换库。
  • 动画转换:动画转换库的项目网站,其中含有通过 BSD 许可的完整源代码。
  • Filthy Rich Clients 演示 :这个项目网站含有这本书的演示程序,其中含有两个动画转换演示程序。
  • Timing Framework:动画转换所使用的底层动画库的项目网站。
  • 我的博客:其中讨论了与本站相关的各类主题,包括图形、动画和桌面 Java。
  • SmoothMoves:j ava.net 上的一篇文章,讨论了增进动画质量的各种关键元素。
  • How to Use the AnimatedTransition API (SwingX and Timingframework):Nazmul Idris 撰写的一篇 Developerlife.com 教程,介 绍了动画转换的基本知识和使用方法。
  • Aerith:这个 Smashup(Swing Mashup) 应用程序使用早期版本的动画转换代码实现了同时淡出及淡入的转换。