用 ActionScript 开发高级可视化组件
我们可以用ActionScript开发在Adobe® Flex™应用中使用的高级可视化组件,这个主题,包
括以下方面的内容:
1. 关于创建高级组件
2. 组件的实现
3. 使组件具备可访问性
4. 为组件增加版本号
5. 组件设计的最佳实践
6. 例子:创建一个复合组件
7. 疑难问题
译者相关说明:
翻译:兰天陕西新东方信息自动化有限责任公司
QQ:5995534098
Blog:http://ltian.javaeye.com
目的:在工作中需要使用Flex,在阅读文档时总是怕遗忘,所以记录下来,以备遗忘。另外,分发给同行共享,为快速提高国
内Flex Web应用开发水平贡献微薄之力,如有不妥之处,请指正。另外期望更多人加入到对Flexhelp翻译的行列中来。
1. 关于创建高级组件
简单组件一般都是现存 Flex 组件的子类,它们通过设置 skpins 或 styles 属性来修改父组
件的外观,或者添加一些新的功能。比如,为 Button 控件增加一个新的事件类型,或者更改
DataGrid 控件缺省的 styles 和 skins。更多信息参见,Simple Visual Components in
ActionScript.
在高级组件中,通常会执行以下动作:
z 更改已有组件的可视化外观或者可视化特性。
z 创建复合组件,将两个或者多个组件包装在其中。
z 通过继承 UIComponent 类来创建组件。
我们通常用继承现存类的方式来创建组件。比如,要创建基于 Button 的控件,我们就创建
mx.controls.Button 类的一个子类。要开发自己的组件,则需要创建 mx.core.UIComponent 类
的子类。
关于重载 UIComponent 类的 protected 方法
Flex 所有的可视化组件都是 UIComponent 类的子类。因此,可视化组件继承了 UIComponent
类所定义的 methods,properties,events,styles 和 effects。
要创建高级的可视化组件,必须实现一个构造器(constructor)。另外要有选择性地重载
下表中 UIComponent 类的一个或者多个 protected 方法:
UIComponent 方法 描述
commitProperties()
提交组件所有的属性变化。要么使属性同时更改,要么确保属性按
照特定顺序设置。
更多信息参见:实现 commitProperties()方法。
createChildren()
创建组件的子组件。比如,ComboBox 控件包含了一个 TextInput 控
件和一个 Button 控件作为它的子组件。更多信息参见:实现
createChildren() 方法.
layoutChrome()
定义 Container 类的子类容器的 border 区域。
更多信息参见:实现 layoutChrome() 方法.
measure()
设置组件的缺省 size 和缺省的最小 size。
更多信息参见:实现 measure()方法 .
updateDisplayList()
根据以前所设置的属性和样式来确定组件的子组件在屏幕上的大小
(size)及位置(position),并且画出组件所使用的所有皮肤
( skins)及图形化元素。组件的父容器负责确定组件本身大小
(size)。
更多信息参见:实现 updateDisplayList() 方法.
组件的使用者不会直接调用所有这些方法;Flex 调用这些方法。更多信息见 “关于组件实
例化生命周期”。
关于失效(机制)的方法
在组件的生命周期中,应用可能会改变组件的大小和位置,更改组件的属性来控制组件的
显示,或者更改组件的样式(styles)和皮肤(skin)属性。比如,可以更改组件中所显示的
文本(Text )的字体(Font)大小。 作为变更字体大小工作的一部分,组件的大小也可能随之发
生变化,这就需要 Flex 去更新应用的布局。布局操作需要 Flex 调用自定义组件的
commitProperties(), measure(), layoutChrome(), 以及 updateDisplayList()方法。
应用通过程序来更改字体大小的执行速度大大快于 Flex 更新应用的速度。因此,你应该在
确定最终要更改的字体之后再更新布局。
另外一个场景就是,当你设置了组件的多个属性后,比如 Button 控件的 label 和 icon 属
性,你肯定会想让所有属性被设置后一次性执行 commitProperties(), measure(), 和
updateDisplayList()方法,而不是设置过 label 属性后执行一遍这些方法,然后在设置 icon
属性后又执行一次这些方法。
另外,可能有几个组件同时改变了它们的字体大小。这时应该让 Flex 去协调布局操作,以
消除任何冗余过程,而不是在每个组件更新它的字体大小之后都执行一次布局操作。
Flex 使用一种“失效机制(invalidation mechanism)”来同步组件的更改。Flex 用一系
列方法的调用来标记组件的某些东西已经发生变化,并需要 Flex 去调用组件的
commitProperties(), measure(), layoutChrome(),或者 updateDisplayList()方法。通过这种
办法,Flex 实现了“失效机制”。
下表描述了有关“失效(invalidation)”方法:
失效(Invalidation) 方法 描述
invalidateProperties()
通知组件,以使下次屏幕更新时,它的 commitProperties()
方法能被调用。
invalidateSize()
通知组件,以使下次屏幕更新时,它的 measure()方法能被
调用。
invalidateDisplayList()
通知组件,以使下次屏幕更新时它的 layoutChrome()方法和
updateDisplayList()方法能被调用。
当组件调用一个“失效”方法,它就通知 Flex,该组件已经被更新。当多个组件调用失效
方法,Flex 会协调这些更新,以使这些更新操作下一次屏幕更新时一起执行。
通常,组件使用者不必直接调用这些“失效”方法。这些”失效”方法被组件的 setter 方
法或者组件的其他方法在需要的时候调用.更多信息参见实现 commitProperties()方法.
关于组件实例化的生命周期
组件实例化生命周期描述了用组件类创建组件对象时所发生的一系列步骤.作为生命周期
的一部分,Flex 自动调用组件的方法,发出事件,并使组件可见。
下面例子用 ActionScript 创建一个 Button 控件,并将其加入到容器之中:
//创建一个 Box 容器。
var boxContainer:Box = new Box();
//设置 Box 容器
…
//创建 Button 控件。
var b:Button = new Button()
// 设置 button 控件。
b.label = "Submit";
...
// 将 Button 添加到 Box 容器中。
boxContainer.addChild(b);
下面的步骤显示了用代码创建一个 Button 控件,并将这个控件添加到 Box 容器中时所发生
的一切:
1. 调用了组件的构造函数,如下面代码所示:
// Create a Button control.
var b:Button = new Button()
2. 通过设置组件的属性对组件进行了设置,如下面代码所示:
// Configure the button control.
b.label = "Submit";
组 件 的 setter 方 法 将会调用 invalidateProperties(), invalidateSize(), 或 者
invalidateDisplayList() 方法.
3. 调用 addChild()方法将该组件添加到父组件中,如下代码所示:
// Add the Button control to the Box container.
boxContainer.addChild(b);
Flex 执行以下动作:
4. 将 component 的 parent 属性设置为对父容器的引用.
5. 计算组件的样式(style) 设置.
6. 在组件上分发
preinitialize 事件.
7. 调用组件的
createChildren() 方法.
8. 调用 invalidateProperties(), invalidateSize()和 invalidateDisplayList()方法以触发后续到来的,下一
个“渲染事件”(renderevent)期间对 commitProperties(), measure(),或 updateDisplayList()方
法的调用。
这个规则唯一一个例外就是当用户设置组件的 height 和 width 属性时, Flex 不会调用
measure() 方法.
9. 在组件上分发 initialize 事件。此时,组件所有的子组件都被初始化,但是组件没有改更
size 和处理布局。可以利用这个事件在组件布局之前执行一些附加的处理。
10. 在父容器上分发 childAdd 事件.
11. 在父容器上分发 initialize 事件.