Avg. Rating 5.0

Problem

Bitmap or BitmapData can not be used as icon in Flex components like mx:Button

Solution

Create cache of special classes. Each of them will be able to become an icon.

Detailed explanation

Flex SDK allows to set "icon" style of <mx:Button/> (and other icon-styles of other components) only Class that instantiates in IFlexDisplayObject. It is usually done as:

[Embed("mouse.png")]
private var icon1:Class;

<mx:Button icon="{icon1}"/>

Problem is that mouse.png can be defined at runtime.

Possible solutions

Compile images as they arrive and load them as SWf at runtime. This method is not always available and is not convinient.

Monkey-patch components in SDK. Flex SDK version change can cause patch break. Also monkey patching brings troubles with RSL.

Generate SWF with image class on the fly. To do this you need to read SWF Specification and AVM2 Bytecode. During reading compiled SWF with 1 opaque PNG I've found that opacity mask seem to be stored separately from color values. All in all do not expect and easy solution. By the way I've found that smallest SWF is about 30 bytes.

Use several precompiled classes and associate them with BitmapData in runtime. This is our way.

Cache of BitmapAsset ancestors.


View Source

Image class should just call parent constructor of BitmapAsset with passing corresponding BitmapData:

public class RuntimeBitmapAsset extends BitmapAsset
{
        
    /**
     *  Maps class names to BitmapData instances.
     */
    public static const bitmapDatas:Object = {};
    
    public function RuntimeBitmapAsset()
    {
        var name:String = getQualifiedClassName(this);
        var bitmapData:BitmapData = bitmapDatas[name];
        if (!bitmapData)
            trace("Warning: BitmapData for \"" + name
                + "\" not found");
        super(bitmapData, PixelSnapping.AUTO, true);
    }    
}

Create as much classes as you need - B0, B1, B2 ...:

public class B0 extends RuntimeBitmapAsset
{
}

Usage

/**
 *  Array of Class-es.
 */
private var bitmapClasses:Array = [ B0, B1, B2 ];

private function addSample():void
{
    if (container.numChildren == bitmapClasses.length)
        container.removeChildAt(0);
        
    var button:Button = new Button();
    button.label = "Button with icon using cache class B" +
index; 
    var theClass:Class = getNextBitmapClass(getRandomBitmapData());
    button.setStyle("icon", theClass);
    container.addChild(button); 
}

private function getNextBitmapClass(bitmapData:BitmapData):Class
{
    // see in View Source
}

private function getRandomBitmapData():BitmapData
{
    // see in View Source
}

+
This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License. Permissions beyond the scope of this license, pertaining to the examples of code included within this work are available at Adobe.

Report abuse

Related recipes