在上一篇文章中我演示了如何基于一个既有的MXML组件——HBox来创建一个组件。在本文中我们将使用ActionScript 写一个同样的组件。我认为这个练习很有价值,因为这会让你明白MXML组件和ActionScript 组件是多么相似。
将 -keep-generated-actionscript=true 添加到Flex编译器选项中是一个不错的尝试,这样MXML文件首先就会被转换成ActionScript类,然后再编译成SWF文件。设置-keep-generated-actionscript参数会将转换的中间ActionScript类保留下来,这样我们就可以对比一下我们将要编写的ActionScript组件和编译器自动生成的ActionScript类。
看一下上篇文章中的MXML组件,它有四个部分:根标签(HBox),Event元数据标签,Script块以及子组件(LinkButton 和 Image)。当你用ActionScript编写该组件的时候你将会明白这些元素都对应什么东西。
下载源文件(貌似下不下来了)
上面是本文例子的源码,里面还包含了一个图标文件。
创建一个名为CycleSelectButtonV2的ActionScript类,并使其扩展自HBox。你可以使用Flex Builder的向导,或者直接使用下面的代码创建类:
package com.adobe.examples.buttons
{
import mx.containers.HBox;
public class CycleSelectButtonV2 extends HBox
{
public function CycleSelectButtonV2()
{
super();
}
}
}
上面所说的MXML组件的四部分中的一个已经出现了:这个类扩展自HBox。
MXML组件还包含一个Event元数据标签,将它添加到ActionScript类中的类定义上面:
package com.adobe.examples.buttons
{
import mx.containers.HBox;
[Event(name="change",type="flash.events.Event")]
public class CycleSelectButtonV2 extends HBox
{
…
至于子控件Image 和 LinkButton就需要编写一些ActionScript代码来实现。上篇文章中我已经提及过Flex框架是如何通过调用commitProperties()来设定属性以及其他一些东西,而创建子组件也是框架的一部分功能。
当一个组件被创建的时候Flex框架就调用createChildren()函数,无论是创建像HBox这样的容器类还是Button这样的控件。要创建LinkButton 和 Image组件,你需要覆写createChildren()函数。
在V2 ActionScript文件中,将下面的语句添加到HBox的导入语句后面:
import mx.controls.LinkButton;
import mx.controls.Image;
Image 和 LinkButton的MXML标签创建了两个类成员,你可以使用ActionScript做同样的事情,将下面的代码添加到构造函数后面:
private var linkButton:LinkButton;
private var image:Image;
MXML文件中的子组件是公有的(public),这里我想将他们变成私有的(private),当然,你可以根据自己的意愿将它们声明成保护(protected)或者公有的(public)。
你还需要导入环形按钮的图片。在MXML文件中图片是直接嵌入在Image标签中的,在ActionScript中没有类似的操作,你需要将下面的代码添加到变量声明的后面:
[Embed(source="../assets/cycle_component.gif")]
private var cycleIcon:Class;
Embed元数据标签告诉编译器从文件中获取字节然后生成一个类。cycleIcon变量的数据类型是Class,因为我们不想创建两个图像(那样会占用太多内存),而只是要共享引用那些字节的实例。
现在添加createChildren()函数:
override protected function createChildren() : void
{
image = new Image();
image.width = 20;
image.height = 20;
image.source = cycleIcon;
addChild(image);
linkButton = new LinkButton();
addChild(linkButton);
super.createChildren();
}
这里创建了一个Image类的实例,然后设定了它的width,height以及source属性。同时也创建了一个LinkButton。注意这两个组件是怎样通过addChild()函数被作为子组件添加的,这个函数将这些子组件放到了显示列表里,如果不使用addChild()函数这些组件就不会显示。使用new操作符和addChild()来创建组件和使用MXML标签创建组件效果是一样的。
createChildren函数是在commitProperties()函数被调用之前调用的,这样你就可以为子组件添加属性了。现在你要做得就是从V1的组件中将setter和getter以及commitProperties()函数直接复制过来。
随着子组件LinkButton 和 Image的创建与设定,现在又实现了上例MXML组件的一部分。
在上一篇文章中,你可以看到Flex框架中包括了对组件大小的计算。MXML组件做得一个重要的事情就是计算所有元素的大小和位置,而在ActionScript组件中你需要自己编写代码来实现。
由于我们使用了HBox作为组件的基类,所以已经有了计算子组件大小和位置的功能。以后我们将从零开始编写一个组件,你将看到如何自己编写代码来实现这些功能。
这个时候所缺少的唯一东西就是LinkButton的click事件处理器了。回到createChildren()函数将下面的一行代码添加到创建linkButton之后:
linkButton.addEventListener(MouseEvent.CLICK, handleClick);
这里你还需要导入flash.events.MouseEvent 类。
使用addEventListener()函数与将事件处理器写到MXML标签中实现的功能是一样的。
现在将V1组件中的handleClick()直接复制过来并做以下更改:
private function handleClick( event:MouseEvent ) : void
{
selectedIndex = selectedIndex + 1;
// wrap back to zero if more than the # of items in the dataProvider.
if( selectedIndex >= dataProvider.length ) selectedIndex = 0;
dispatchEvent( new Event(Event.CHANGE) );
}
使用MXML标签的时候你可以方便地决定向事件处理器中传送什么参数,而使用addEventListener函数的时候事件处理器就只能有一个参数。如果你阅读了关于LinkButton的文档并了解了它的click事件的话,你将看到它分派了一个MouseEvent,这样数据类型就会被作为参数传送到事件处理器中。
打开Flex主程序并将所有的CycleSelectButtonV1标签更改为CycleSelectButtonV2并运行它,运行结果和上例应该没有什么两样。
旋转箭头
在上篇文章中我提到过,除了要使用ActionScript重写这个组件以外,我们还将在每次LinkButton被点击的时候旋转箭头图像。我已经将这部分代码放在上面的下载文件中了,你可以自己看一下,这将是下一篇文章的主题。
|