Flex4 自定义通用的ImageButton

Flex4与之前版本的一个极大区别就是外观皮肤的分离,虽然进一步解耦,但存在一个不爽的地方就是增加了编码的工作量,你能想象为你的每个自定义组件都写一个对应的皮肤吗?可能仅仅和你之前写过的组件差了那么一点点而已,可是工作量double,更进一步使代码的管理复杂化。

下面是我自己写的一个通用的自定义ImageButton,有呆毛(Demo)才有真相:

1.首先创建一个Skinnable组件,继承自Button(一个很大的好处就是支持defaultButton,普通的组件是不支持的,这是促成我写这个组件的原始动力),类名就定义为ImageButton:

package cn.shawnlee.components

{

    import spark.components.Button;

    public class ImageButton extends Button

    {    

          public function ImageButton()

          {

               super();    

          }  

     }

}

2.好了,组件已经建立了,然后先建立一个皮肤,再来考虑逻辑,新建MXML外观,定义为ImageButtonSkin,主机组件定位到刚才建立的ImageButton:

<?xml version="1.0" encoding="utf-8"?>

<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009" 

        xmlns:s="library://ns.adobe.com/flex/spark" 

        xmlns:mx="library://ns.adobe.com/flex/mx">

    

    <!-- host component -->

    <fx:Metadata>

        [HostComponent("cn.shawnlee.components.ImageButton")]

    </fx:Metadata>

    

    <!-- states -->

    <s:states>

        <s:State name="disabled" />

        <s:State name="down" />

        <s:State name="over" />

        <s:State name="up" />

    </s:states>

    

    <!-- SkinParts

    name=iconDisplay, type=spark.primitives.BitmapImage, required=false

    name=labelDisplay, type=spark.core.IDisplayText, required=false

    -->

    

</s:Skin>

3.现在来考虑显示逻辑,我们仅仅需要用图片来代替按钮的默认外观,但考虑到按钮的四种状态,我需要用四个BitmapImage来分别装载四个图片,用来在不同状态下显示,因此,在外观中直接加入

<s:BitmapImage id="imageDisabledDisplay" includeIn="disabled" />

<s:BitmapImage id="imageDownDisplay" includeIn="down" />

<s:BitmapImage id="imageOverDisplay" includeIn="over" />

<s:BitmapImage id="imageUpDisplay" includeIn="up" />

4.由此外观皮肤已经做好了,对,就这么简单,下面只需要在显示逻辑上做文章就可以了,来看看ImageButton类,我们需要把外观中加入的四个BitmapImage在类中进行定义声明,以便可以在代码中进行调用和控制:

[SkinPart(require="false")]

public var imageDisabledDisplay:BitmapImage;

        

[SkinPart(require="false")]

public var imageDownDisplay:BitmapImage;

        

[SkinPart(require="false")]

public var imageOverDisplay:BitmapImage;

        

[SkinPart(require="false")]

public var imageUpDisplay:BitmapImage;

5.接下来考虑显示逻辑,我希望我的组件能够很方便的这么使用:

<cn:ImageButton image="@Embed('./btn.png')" imageDown="@Embed('./btnDown.png')" imageOver="@Embed('./btnOver.png')" />

如果我比较懒,我只是需要一张图片,那么就只定义image,如果我还想详细的定义up,down,over,disabled状态下的图片,则通过imageUp,imageDown,imageOver,imageDisabled来定义,所以我的组件需要自定义五个Style样式:

[Style(name="image", type="Class", format="EmbeddedFile", inherit="no")]

[Style(name="imageDisabled", type="Class", format="EmbeddedFile", inherit="no")]

[Style(name="imageDown", type="Class", format="EmbeddedFile", inherit="no")]

[Style(name="imageOver", type="Class", format="EmbeddedFile", inherit="no")]

[Style(name="imageUp", type="Class", format="EmbeddedFile", inherit="no")]

public class ImageButton extends Button

6.好了,image样式表示默认的图片,如果没有设置对应状态下的图片,则以image样式的图片显示,为此,我需要自定义一个私有方法,来返回各个状态下应该显示出的图片:

private function getImageStyle(styleProp:String):*

{

    var value:* = getStyle(styleProp);

    return  value==null?getStyle("image"):value;

}

7.然后就是自定义组件不可缺少的一步,重写partAdded方法:

override protected function partAdded(partName:String, instance:Object):void

{

    super.partAdded(partName, instance);

    if(instance == imageDisabledDisplay)

    {

        imageDisabledDisplay.source = getImageStyle("imageDisabled");

    }

    if(instance == imageDownDisplay)

    {

        imageDownDisplay.source = getImageStyle("imageDown");

    }

    if(instance == imageOverDisplay)

    {

        imageOverDisplay.source = getImageStyle("imageOver");

    }

    if(instance == imageUpDisplay)

    {

        imageUpDisplay.source = getImageStyle("imageUp");

    }

}

上面的过程使ImageButton在添加各个BitmapImage子组件时根据对应的Style样式设置各自的图片source属性,至此,组件完成,是不是很简单?

源代码下载

你可能感兴趣的:(imagebutton)