Programmatic Skinning in Flex 2 Beta 2

This example application shows how to skin components using programmatic skins. These are skins which are written in ActionScript. The other type of skins, graphic skins, are images. You can combine the two skins as well as use them separately.

If you open the main application file, SkinningExample.mxml, you will see the <mx:Style> section. When you create skins you typically want all of the controls to have the same look. You may, for example, want only LinkButtons to have your special look, or, as in this example, you want many components to have your look.

You can run the application from this URL: http://www.keaura.com/skinning

This application works only with Flex 2 Beta 2 and the Flash Player 8.5 that goes with that release. The source is available from a right-click on the application once you have launched it. I used the application source packaging feature of Flex Builder 2.

Since I have created so many skins you might think to yourself that I have created a theme. This is fairly accurate, but I have not packaged these skins as such. I’ll leave that for a future article.

Disclaimer

I am not an artist. I will not be offended if you think these skins are unattractive. The point is learn how to do skinning, not to make a MOMA piece. You can call this collection of skins my Orange Period.

Specifying Skins

We’ll start with a top-down approach and look at how you specify the skins and relate them to the components. I’ve done this with styles, but you can also place these styles on individual component definitions – it just depends on what you want skinned.

This is the style definition for a Button:

Button {
upSkin: 		ClassReference("skins.MyButtonSkin");
overSkin: 		ClassReference("skins.MyButtonSkin");
downSkin: 		ClassReference("skins.MyButtonSkin");
disabledSkin: 	ClassReference("skins.MyButtonSkin");
}

The names of the skins are found in the Flex component API under the style section. The ClassReference style attribute names the ActionScript class which defines that skin. You can see that I have specified the same ActionScript class for each of the skins listed for the Button. When you see the code for the class it will be more obvious why I did it that way. Many times a skin for each state or part of a component share the same code and it often makes sense to use the same class. But you do not have to do that, you can write a separate class for every skin.

This is the code for the skins.MyButtonSkin class.

package skins {
import mx.skins.ProgrammaticSkin;
import flash.display.*;

public class MyButtonSkin extends mx.skins.ProgrammaticSkin {

private var _backgroundFillColor:uint;
private var _lineThickness:int;

public function MyButtonSkin()
{
_backgroundFillColor = 0xFFBB00;
_lineThickness       = 1;
}

override protected function updateDisplayList( w:Number, h:Number ) : void
{
var g:Graphics = graphics;

if( getStyle("lineThickness") ) {
_lineThickness = getStyle("lineThickness");
}
if( getStyle("backgroundFillColor") ) {
_backgroundFillColor = getStyle("backgroundFillColor");
}

switch( name ) {
case "upSkin":
break;
case "overSkin": // make lighter
_backgroundFillColor = 0xFFCC00;
break;
case "downSkin": // make darker
_backgroundFillColor = 0xFFAA00;
break;
case "disabledSkin":
_backgroundFillColor = 0x999999;
break;
}

g.clear();

// now draw the real button
g.beginFill(_backgroundFillColor,1.0);
g.lineStyle(_lineThickness,0x000000,0.4);
g.moveTo(w,0);
g.lineTo(10,0);
g.curveTo(0,0,0,10);
g.lineTo(0,h);
g.lineTo(w-10,h);
g.curveTo(w,h,w,h-10);
g.lineTo(w,0);
g.endFill();
}
}
}

I have two class variables: _backgroundFillColor and _lineThickness which I initialize in the class constructor function.

Perhaps the most important piece of the skin is the updateDisplayList function. This function is declared as an override because it is replacing the function of the same signature in the base class, mx.skins.ProgrammaticSkin. It is in this function that the skin is drawn. Flex will call upon this function whenever it needs to have the skin drawn.

Within the updateDisplayList function you can see where the name of the skin is being tested. Look back to the Style section and you can see those names: “upSkin”, “downSkin”, and so forth. These names correspond to the case clauses in the switch statement. The only difference between the skins is the color. For “upSkin” and “downSkin” is tried to lighten and darken the color a bit. For “disabledSkin” I made it gray.

The button graphic is drawn using the drawing functions of the graphics property of the component. The graphics property does have some handy drawing functions, such as drawRect and drawCircle. You can read more about this class under flash.display.Graphics.

Another thing to notice in the updateDisplayList function is how the color and line style are set. While I did initialize these in the class constructor, I test the component’s style for settings that would override the defaults.

The rest of the skins work in a similar fashion and you should have no problem adapting them. Just be sure to read all of the API information for the components you want to skin. Skins for scrollbars are often referenced via custom styles. One example is the Panel which you can see in the Style section.

Skinning in Flex 2 is fairly straightforward and once you get the hang of it you will be able to create innovative skins. Just let your imagination run wild.