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属性,至此,组件完成,是不是很简单?

源代码下载

原文地址:https://www.cnblogs.com/niss/p/3349302.html