A skin is a piece of code or a graphic that you apply to a component to change the way it displays or the way it behaves. This is because a skin is based on a user interface component. You can also apply styles to skins to further customize the component (you will learn that in the next section). For this article, the skin you apply only changes the way the component displays.
In a typical developer workflow, you or other developers would create new skins and apply them to an existing component. In the Analog Clock component you built in part one, you would first identify the parts you want to skin, which, in this case, are the face and the three hands (hour, minute, and second). You might decide to use the same skin for all of the hands, or you might use a separate skin for each hand. For this tutorial, I used the same skin for all the hands (you can always take it one step further if you like). Lastly, you will learn how to change the skin with code and a graphic.
To skin the original Analog Clock, unzip the files for the face and hands from the ZIP file you downloaded from the Requirements section.
In the following steps, you will reskin the clock face using code. The same steps also apply to reskinning the hands, so I did not include them in this tutorial.
drawFace() function from the AnalogClock_Styled.as component file and paste it into the AnalogClockFaceSkin.as class file between the opening and closes braces of the class. drawFace() function to draw(). (The code that draws the clock face is the drawFace() function, but now the draw() function will draw the clock face.)Use the following steps to create the AnalogClock.as class file.
AnalogClock_Styled to AnalogClock.drawFace() function as this is now handled by the AnalogClockFaceSkin class.Add the following code to the createChildren() function, which instantiates the skin class.
createClassObject( clockFaceSkin, "face_mc", getNextHighestDepth(), {styleName:this});
This code replaces: createEmptyMovieClip("face_mc",getNextHighestDepth()); from the original file.
Add the following code to the layoutChildren() function, which positions the skin.
face_mc.move(cx,cy); face_mc.setSize(layoutWidth,layoutHeight);
This code replaces: face_mc._x = cx; face_mx._y = cy; from the original file.
static function classConstruct():Boolean
{
AnalogClock.prototype.clockFaceSkin = AnalogClockFaceSkin;
return true;
}
static var classConstructed:Boolean = classConstruct();
static var AnalogClockFaceSkinDependency:AnalogClockFaceSkin = AnalogClockFaceSkin;
Note: This last step may seem unnecessary, but there is a reason. Flex is another way for you to author Flash content. You must make the skin components available to, or load them into Flash Player when you or your application instantiates the AnalogClock class. To ensure that the skins are loaded before the core component, you use this code to create a dependency between the skin class and component class; such a dependency loads the skin class before the component class.
I recommend using this sequence whenever creating a skin.
Test the skin by browsing clockTest.mxml.
Notice that AnalogClock and AnalogClock_Styled components look the same.
The solution files show you how to add skins for the hands.
In the following steps, you will skin the clock face using a graphic instead of code. The same steps also apply to reskinning the hands, so I did not include them in this tutorial.
You create graphic skins with a graphic image editor, such as Macromedia Flash or Fireworks. I use Flash because it keeps all of the skins in a single file and I can reference them by name.
The AnalogClock.as file needs a few more modifications to work with the graphical and code-based skins.
Add the following code to the AnalogClock class file, above the init()method:
private var idNames:Array = ["face_mc","minuteHand_mc","hourHand_mc","secondHand_mc","mouseHover_mc"];
Replace the code you just added for the face skin in the createChildren() method with the following statements:
if( typeof(clockFaceSkin) == "function" ) {
createClassObject( clockFaceSkin, "face_mc", getNextHighestDepth(), {styleName:this});
} else {
setSkin( 0, clockFaceSkin, {styleName:this} );
}
The if-statement tests the value type stored in the clockFaceSkin variable. If it is a “function”, it means that the component is using a class as a code-based skin; if the test fails, then the component is using a graphic skin. The setSkin method uses the first parameter (0 in this example), to index the idNames array from step 1.
Replace the code you just added for the face skin for the layoutChildren() method with these statements:
if( typeof(clockFaceSkin) == "function" ) {
face_mc.move(cx,cy);
face_mc.setSize(layoutWidth,layoutHeight);
} else {
face_mc._x = cx
face_mc._y = cy;
}
The position of the skin depends on its type. When you code your own components, this may change as it depends on the (0,0) origin of the graphic elements in the skin.
You have changed the code to accept a graphic and a code-based skin. Next, you’ll create the graphic skin.
I used Macromedia Flash to make a Flash document that contains a symbol for each skin. For example, if you open the ClockSkins.fla file you will see the following skins:
Figure 1. Skins available with the ClockSkins.fla file
Each of the images is a symbol. The face symbol is named “ClockFace.” Create an MXML application file and include the following ActionScript and tags to display a clock that uses the face skin above:
<mx:Script> <![CDATA[ [Embed(source=”ClockSkins.swf”,symbol=”ClockFace”)] var clockFace:String; ]]> </mx:Script>
The Embed directive instructs the ActionScript compiler to load the ClockFace symbol from the ClockSkins.swf file and assign the name to the variable, clockFace. You include an Embed directive and variable declaration for every skin you use.
<local:AnalogClock clockFaceSkin=”ClockFace” width=”200” height=”200” / >
You can find the clockFaceSkin property in the AnalogClock class and assign it with the symbol name. When the AnalogClock code runs, the if-statement in the createChildren() method will not be a “function,” and so, will associate the symbol with the skin for the face.
Skinning a component is about planning and determining how detailed you want to be. In this example I chose to skin the face and hands and to make the skins either graphic or code-based. You could decide that you want only code-based skins. Or if your design calls for intricate details that would be hard to produce in code, use graphic skins.
I also chose to limit the number of skins, but I could extend this example to have skins for the tick marks as well.