天天看点

Flex 自定义组件

  flex 自定义组件 (2009-10-20 16:11:43)

<script> var $tag='it'; var $tag_code='6eff2243401bc476fcc3abc417b161d1'; </script> 标签:it   分类:Flex

实现一个自定义组件

   Flex组件开发可分为两种. 一是在mxml中创建自定义组件.另一种则在actionscript class中创建. 总体说来其实大同小异. 首先我们要转换一种观点. mxml组件文件和ActionScript class文件一样都是类.开发者都可以在语法和机制上new 这个类的. 比如两个一模一样的组件.MyButton.mxml 和 MyButton.as. 当我们想要在某一个as函数中动态的创建这个自定义按钮时,都可以.

public var tempButton:MyButton = new MyButton();

parentPanel.addChild(tempButton);

  当我们自定义组件时,有若干问题要注意.

1. 如果我们想要给这个新组件添加一个属性,只要在组件类中声明这个变量为public就可以了.

2. 如果想要给这个组件添加一个自定义事件,只要在组件类定义这个Event然后addEventListener就可以了.

3. 如果此组件需要一些Util工具函数,只要在组件定义类内部把这个工具函数public static就可以了.

4. 如果你的组件比较复杂并且存在数据相互依存,那么建议最好将组件的createPolicy设置为"all", default为"auto",

如果要创建一个自定义组件,你需要重写UIComponent类的某些方法,最少需要重写如下方法:构造函数, createChildren(), commitProperties(), measure(), layoutChrome(), updateDisplayList() 。

基础语句结构如下:

package myComponents

{

public class MyComponent extends UIComponent

{    .... }

}

注意包名与你的磁盘目录结构一致。接下来一一讲解每个方法的重写。

构造函数

示例如下:

public function 类名() {

super();

}

注意,AS3中构造函数不支持重载。

createChildren()

此方法的作用是在此自定义组件中创建子组件。

此方法不用你去调用,Flex在你将此自定义组件使用addChild方法加入到父组件时自动调用。示例如下:

// Declare two variables for the component children.

private var text_mc:TextArea;

private var mode_mc:Button;

override protected function createChildren():void {

    // Call the createChildren() method of the superclass.

    super.createChildren();

    // Test for the existence of the children before creating them.

    // This is optional, but do this so a subclass can create a different

    // child.

    if (!text_mc)     {

        text_mc = new TextArea();

        text_mc.explicitWidth = 80;

        text_mc.editable = false;

        text_mc.addEventListener("change", handleChangeEvent);

        // Add the child component to the custom component.

        addChild(text_mc);

    }

    // Test for the existence of the children before creating them.

    if (!mode_mc)     {    

        mode_mc = new Button();

        mode_mc.label = "Toggle Editing";

        mode_mc.addEventListener("click", handleClickEvent);

        // Add the child component to the custom component.

        addChild(mode_mc);

    }

}

上例使用createChildren()在此自定义组件中加入了一个Label和一个Button。

commitProperties()

此方法是在修改组件属性时使用。

此方法不用你去调用。当你调用invalidateProperties()(刷新属性)、addChild()(增加子组件)方法时,Flex会自动调用此方法。这样组件在下次显示时,就能以新的属性来显示。

此方法还有一个作用是为measure()方法提供最新的属性信息。

measure()

此方法的作用是设置组件的默认尺寸。

此方法不用你去调用。当你调用invalidateSize ()(刷新尺寸)、addChild()(增加子组件)方法时,Flex会自动调用此方法。这样组件在下次显示时,就能以默认尺寸来显示。

如果你显式的设置了组件的尺寸,如<mx:Button height="10" width="10"/>,Flex就不用调用此方法了。要注意,measure()方法只是设置组件的默认尺寸,在updateDisplayList()方法中,组件具备的实际尺寸(actual size)与默认尺寸可能不同。

Flex中的每个组件都是有默认尺寸的。如这样写:<mx:Button />,Flex就会自动给一个尺寸。如果你想重写默认尺寸,可以重新设置measuredHeight 、measuredWidth、measuredMinHeight、measuredMinWidth。如下例:

package myComponents

{

    // asAdvanced/myComponents/DeleteTextArea.as

    import mx.controls.Button;

    public class BlueButton extends Button {

        public function BlueButton() {

            super();

        }

       override protected function measure():void {

            super.measure();

            measuredWidth=100;

            measuredMinWidth=50;

            measuredHeight=50;

            measuredMinHeight=25;

        }

    }

}

然后在MXML中使用:

<?xml version="1.0"?> 

<!-- asAdvanced/ASAdvancedMainBlueButton.mxml -->

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" 

    xmlns:MyComp="myComponents.*" >

    <mx:VBox>

        <MyComp:BlueButton/>

        <mx:Button/>

    </mx:VBox>

</mx:Application>

此中的BlueButton就会以默认值100宽,50高来显示。

layoutChrome()

一些容器类(Container)或其子类采用此方法设置组件的border Area(边框区域)。

此方法不用你去调用。当你调用invalidateDisplayList ()(刷新显示)方法时,Flex会自动调用此方法。这样组件在下次显示时,就能以新的边框来显示。

典型的用法是你可以重写RectangularBorder类。

一个将组件的边框区域(border Area)和内容区域(content area)分开处理的原因是当Container.autoLayout=false时。

总括的来讲,layoutChrome()是用来处理边框区域的刷新显示,而updateDisplayList()用来处理内容区域的刷新显示。

updateDisplayList()

此方法不用你去调用。当你调用invalidateDisplayList ()(刷新显示)、addChild()(增加子组件)方法时,Flex会自动调用此方法。这样组件在下次显示时,就能以新的样子来显示。其实类似VC++中的PAINT消息处理。

此方法的主要作用为:

A.更改组件的尺寸和位置。要改变尺寸,在此方法中使用setActualSize()方法,而不是使用width和height属性来完成。要改变位置,在此方法中使用move()方法,而不是使用x和y属性来完成。

B.绘制可视元素,如皮肤、样式、边框。你可以使用Flash Drawing API来完成。

函数的原型为:

protected function updateDisplayList(unscaledWidth:Number,

    unscaledHeight:Number):void

两个参数分别为此自定义组件的宽度和高度。当然如果设置父容器设置scaleY=2,你设置unscaledHeight=100,那么最终呈现的是200高度的组件。

第一个功能示例:

package myComponents

    // asAdvanced/myComponents/BottomUpVBox.as

    import mx.containers.VBox;

    import mx.core.EdgeMetrics;

    import mx.core.UIComponent;

    public class BottomUpVBox extends VBox

    {

        public function BottomUpVBox() {

            super();

        }

        override protected function updateDisplayList(unscaledWidth:Number,

            unscaledHeight:Number):void {

            super.updateDisplayList(unscaledWidth, unscaledHeight);

            // Get information about the container border area. 

            // The usable area of the container for its children is the 

            // container size, minus any border areas.

            var vm:EdgeMetrics = viewMetricsAndPadding;

            // Get the setting for the vertical gap between children.

            var gap:Number = getStyle("verticalGap");

            // Determine the y coordinate of the bottom of the usable area 

            // of the VBox.

            var yOfComp:Number = unscaledHeight-vm.bottom;

            // Temp variable for a container child.

            var obj:UIComponent;

            for (var i:int = 0; i < numChildren; i++)

            {

                // Get the first container child.

                obj = UIComponent(getChildAt(i));

                // Determine the y coordinate of the child.

               yOfComp = yOfComp - obj.height;

                // Set the x and y coordinate of the child.

                // Note that you do not change the x coordinate.

                obj.move(obj.x, yOfComp);

                // Save the y coordinate of the child, 

                // plus the vertical gap between children. 

                // This is used to calculate the coordinate 

                // of the next child. 

                yOfComp = yOfComp - gap;

            }

         }

    }

}

第二个功能示例:

override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {

    super.updateDisplayList(unscaledWidth, unscaledHeight);

    // Draw a simple border around the child components.

    graphics.lineStyle(1, 0x000000, 1.0);

    graphics.drawRect(0, 0, unscaledWidth, unscaledHeight);            

}

继续阅读