Introduction
We all like components but where would we be without the skinning features? I for one have rarely used components without customizing their appearance in one way or another.
Flash MX supported skinning to a certain extent but, with the new release of Flash MX 2004 and Flash MX 2004 Professional, we've been given a whole host of new functionality allowing us to change a component's look and feel quickly and efficiently.
This tutorial will run through these new features and explain the various options you have for skinning Flash MX 2004 components step by step.
Before we get started make sure you download the sourcefiles for this tutorial so you'll be able to easily follow what is being discussed.
Using the Styles API
Styles in Flash MX 2004 can best be described as properties that contain information on the way a particular component should be displayed.
These properties can either be stored on the component instance, the component class or in the _global scope. The scope in which the Styles are assigned determines whether the Styles are applied to a single component, all components of the same class (CheckBox, ListBox, etc.) or all components on stage.
We will cover these options later on in this tutorial but first let's take a look at what Styles are supported by Flash MX 2004.
Supported Styles in Flash MX 2004
In this tutorial we'll be working a lot with the ComboBox component. To make things a bit more visual and explain what styles are available, I've made a little diagram of some common styles for the ComboBox.

A complete list of all supported styles and their default values for the UI Components in Flash MX 2004 can be found below.
Style |
Description |
backgroundColor |
The background of a component. This is the only color style that does n 't inherit its value. The default value is transparent. |
borderColor |
The black section of a three-dimensional border or the color section of a two-dimensional border. The default value is 0x000000 (black). |
borderStyle |
The component border: either "none", "inset", "outset", or "solid". This style does not inherit its value. The default value is "solid". |
buttonColor |
The face of a button and a section of the three-dimensional border. The default value is 0xEFEEEF (light gray). |
color |
The text of a component label. The default value is 0x000000 (black). |
disabledColor |
The disabled color for text. The default color is 0x848384 (dark gray). |
fontFamily |
The font name for text. The default value is _sans. |
fontSize |
The point size for the font. The default value is 10. |
fontStyle |
The font style: either "normal" or "italic". The default value is "normal". |
fontWeight |
The font weight: either "normal" or "bold". The default value is "normal". |
highlightColor |
A section of the three-dimensional border. The default value is 0xFFFFFF (white). |
marginLeft |
A number indicating the left margin for text. The default value is 0. |
marginRight |
A number indicating the right margin for text. The default value is 0. |
scrollTrackColor |
The scroll track for a scroll bar. The default value is 0xEFEEEF (light gray). |
shadowColor |
A section of the three-dimensional border. The default value is 0x848384 (dark gray). |
symbolBackgroundColor |
The background color of check boxes and radio buttons. The default value is 0xFFFFFF (white). |
symbolBackgroundDisabledColor |
The background color of check boxes and radio buttons when disabled. The default value is 0xEFEEEF (light gray). |
symbolBackgroundPressedColor |
The background color of check boxes and radio buttons when pressed. The default value is 0xFFFFFF (white). |
symbolColor |
The check mark of a check box or the dot of a radio button. The default value is 0x000000 (black). |
symbolDisabledColor |
The disabled check mark or radio button dot color. The default value is 0x848384 (dark gray). |
textAlign |
The text alignment: either "left", "right", or "center". The default value is "left". |
textDecoration |
The text decoration: either "none" or "underline". The default value is "none". |
textIndent |
A number indicating the text indent. The default value is 0. |
Assigning styles to a component instance (styleInstance.fla)
Assigning styles to a single component instance is very easy indeed.
- Drag an instance of the ComboBox component on Stage.
- Define the components instance name as “myCombo”. On the first frame of the main timeline write the following ActionScript code:
myCombo.setStyle("backgroundColor","0xFFCC00");
If you test this movie you'll find that the ComboBox now has a nice bright yellow background.
You can apply any number of Styles to a component instance simply by using the setStyle() method. To get the value of a particular Style property you use the getStyle() method as illustrated below.
- Add the following line of code to frame 1 of your main timeline:
trace(myCombo.getStyle("backgroundColor")); // outputs 0xFFCC00
If you test your movie at this stage it will set the backgroundColor Style property to yellow as it did before and output the value “0xFFCC00” which we retrieved through using the getStyle() method.
This is all well and good if you're just using one ComboBox component on Stage, but what if you have several? No, you don't need to manually set the Styles for each of your ComboBox components. You can, instead, apply Styles to the component Class, which is what we'll look at next.
Assigning styles for a particular component class (styleClass.fla)
If you want to set Styles for only one particular component class (ComboBox, CheckBox, etc.) this is the way to do it:
- Drag a couple of instances of the ComboBox component on stage.
- Drag an instance of the ScrollPane component on stage.
- On the first frame of your main timeline write the following ActionScript code:
_global.styles.ComboBox = new mx.styles.CSSStyleDeclaration(); _global.styles.ComboBox.setStyle("backgroundColor","0xFFCC00");
What that code does first is create a new class Style declaration in the _global scope. The namespace “styles” is predefined in the _global scope as the location where all component class Style declarations are stored.
The second line of code assigns a value for the backgroundColor Style property in the _global class Style declaration.
If you test this movie you'll notice that all ComboBox components now have the yellow backgroundColor and the ScrollPane component is not affected.
Assigning styles to the _global scope (styleGlobal.fla)
If you would like all components on Stage to have the same Styles applied you can do this by assigning the Style properties to the style namespace in the _global scope.
- Drag some components on Stage (ComboBox, ScrollPane, DateField,etc.)
- On the first frame your main timeline add the following ActionScript code:
_global.style.setStyle("backgroundColor","0xFFCC00");
Notice that we are now defining the Styles in the “style” namespace of the _global scope not the “styles” namespace which we did when assigning Style properties for a particular component class.
If you test your movie you'll see that all components on Stage now have the new backgroundColor assigned.
It is worth noting that some UI components (like TextInput and TextArea) already have styles defined in their component class style declaration. You will notice that these components don't appear to subscribe to the styles you've assigned to the _global.style scope. This is expected behaviour because styles on the component class scope take precedence over _global styles (more about this later in the tutorial).
To bypass this behaviour you can either set the styles manually to each instance of these components like we did earlier in the component or set the styleName property of these components to point to _global.style (you'll see this next, in the section on custom style definitions.)
Making your own custom Style definition (styleCustom.fla)
Things get a bit more difficult when you want to make your own custom Style definition and only apply that to particular components. This is what we'll be looking at right now.
- Drag a ComboBox, ScrollPane and DateField component on Stage.
- Give these components instancenames “skin1”, “skin2” and “skin3”.
- On the first frame of your main timeline add the following ActionScript code:
_global.styles.niceYellow = new mx.styles.CSSStyleDeclaration();
_global.styles.niceYellow.backgroundColor = "0xFFCC00";
skin1.setStyle("styleName","niceYellow");
skin3.setStyle("styleName","niceYellow");
What this code does is it, first of all, creates a new Style declaration in the _global scope and assigns our yellow backgroundColor property to it. Next it sets the styleName properties of the skin1 and skin3 component instances to “niceYellow” (the name we gave our custom Style definition). This makes the components subscribe to the Styles of that particular object in the _global.styles scope.
When you test your movie at this point you'll see that skin1 and skin3 have the yellow background applied and skin2 still has its default backgroundColor.
Styles and inheritance (inheritStyles.fla)
The concept of inheritance may sound complicated but it is actually pretty straightforward (but nevertheless very powerful).
Let's say we've got a ComboBox component inside a ScrollPane component. Now, we can see the ScrollPane as the parent object of the ComboBox, and likewise the ComboBox as the child object of the ScrollPane component. Inheritence allows the child object to subscribe to style properties from its parent if it hasn't had them applied in its own scope.
Let's look at an example:
- Open up a blank FLA document
- Drag an instance of the ScrollPane and the ComboBox component on stage
- Delete the ComboBox component from the stage
- Give the ScrollPane component the instancename “myScrollPane”
What we'll be doing next is setting two styles for the ScrollPane. The first one will be “backgroundColor” which does not inherit. The other style is color which does inherit.
myScrollPane.setStyle("backgroundColor","0xFFCC00");
myScrollPane.setStyle("color","0xCC0000");
Next we'll load a ComboBox component in the ScrollPane, add an item to it and watch what happens.
myScrollPane.attachMovie("ComboBox","myCombo",1);
myScrollPane.myCombo.addItem("Item 1");
If we test our movie at this stage we'll see that the ScrollPane component has the yellow backgroundColor we've assigned it but the ComboBox inside the ScrollPane hasn't. As for the color, we can't see it in the ScrollPane as that component doesn't have any text to color but it has apparently allowed its child object to inherit this value as the ComboBox did take the color style we applied to the ScrollPane.
If, however, we do add a line to our code and set a different color value for the ComboBox component inside the ScrollPane we'll see that the component's own style settings always take precedence over the inherited values.
myScrollPane.myCombo.setStyle("color","0xCCCCCC");
Now isn't that remarkable? When you start doing more complex applications with nested components you'll be able to make good use of this feature and save yourself a lot of time.
Using the StyleManager class you can set inheritance for styles you use when you building your own components in Flash MX 2004. This is beyond the scope of this tutorial but it is good for you to know that it's out there if you need it.
Working with different scoped Styles in one document
You might be wondering what happens if you define various types of Styles, both on the component instance, component class and _global scope.
Flash MX 2004 has a particular order in which it looks for component Styles:
- component instance (myCombo)
- component styleName property in the _global scope (_global.styles.styleName)
- component default Style class definition (_global.styles.ComboBox)
- _global Styles definition (_global.style)
If Flash encounters Style properties on the component instance it applies those and ignores the rest, if not, it checks whether the styleName property for the component was defined and, if so, looks for that Style class definition in _global.styles.
If the styleName property isn't defined for the component instance it looks at the default Style class definition in _global.styles. Finally, if the default Style class doesn't exist and if that particular Style does not inherit it from its parent, it goes looking in the _global.style scope.
It doesn't end there, if the particular Style is set to inherit, Flash goes looking through exactly the same chain in the parent instance of the component. When all parent objects have been searched and it still hasn't found the Style property defined, it goes looking in the _global scope.
This is very some powerful behaviour indeed! It gives developers the ability to build layered and inheriting Styles to an extent that was never seen in Flash before.
Using CSS to style components
Readers familiar with Cascading Style Sheets may already have noticed that the component styles discussed earlier look very similar to the ones they already know. In fact, the TextField object in Flash MX 2004 actually does use these official W3C standard CSS styles.
Why exactly the Macromedia team chose to use slightly different style names for their components remains a complete mystery to me. A good example of this incompatibility is the following:
The TextField.StyleSheet object can parse the official “font-weight” style and use that to determine whether or not a particular style in a textfield is set in bold while the component styles require you to use “fontWeight” to do the exact same thing for components.
There's no reason to despair though, with a little workaround you'll soon by able to use the default W3C standard CSS styles on your components. The process is pretty easy, what you need to do is pass the styles through TextField.StyleSheet, parse them through that objects' parseCSS() method and then feed the result back to a component instance, component class or the _global.style scope.
Without further ado, I'll introduce you to this workaround function:
cssToComponent = function(targetObj,styleObj,styleName) {
var styleObj = eval(styleObj+"."+styleName);
for(var i in styleObj) {
if(styleObj[i].substr(0,1) == "#") { styleObj[i] = "0x"+styleObj[i].substr(1);
}
targetObj.setStyle(i,styleObj[i]);
}
}
Doesn't look too complicated, does it? I'll walk you through each line and explain what it does but first let's see what arguments this function needs. The first argument is “targetObj”, where specify what target the styles from our Style Sheet are assigned to. The second argument is a String that points to the variable containing our parsed CSS data and finally the third argument specifies which style within that Style Sheet we want to apply.
The first line within the function evaluates the object where our styles are stored and then starts a for-in loop through that object. Each style it encounters in the object is applied to our “targetObj” using the setStyle method we discussed earlier.
Observant readers might have noticed that there is another line before setStyle that we haven't discussed yet. What this line does is actually check the value for a style and make sure that all colors are converted into a hexadecimal number (0xFFC00 vs. #FFCC00).
”But how do we get this parsed CSS data?” I hear you asking. Well, this is where another function comes in. You could of course just as easily code this manually but the function below will save you the time of doing so.
loadStyleSheet = function (css, cb) {
var cssData = new LoadVars();
cssData.load(css);
cssData.container = this;
cssData.onData = function(raw) {
var cssResult = new TextField.StyleSheet();
cssResult.parseCSS(raw);
this.container[cb](cssResult._css);
};
};
Now let's see what that function does. It takes two arguments, the first one being a String that points to the external CSS file you want to load into Flash. The second argument is a String value that contains the name of the callBack function that will be triggered once the CSS file is parsed.
Let's put all this code together and look at a finished version.
loadStyleSheet = function (css, cb) {
var cssData = new LoadVars();
cssData.load(css);
cssData.container = this;
cssData.onData = function(raw) {
var cssResult = new TextField.StyleSheet();
cssResult.parseCSS(raw);
this.container[cb](cssResult._css);
};
};
applyCSS = function(cssObj) {
myCSS = cssObj;
cssToComponent(myCombo,"myCSS","myCombo");
}
cssToComponent = function(targetObj,styleObj,styleName) {
var styleObj = eval(styleObj+"."+styleName);
for(var i in styleObj) {
if(styleObj[i].substr(0,1) == "#") { styleObj[i] = "0x"+styleObj[i].substr(1);
}
targetObj.setStyle(i,styleObj[i]);
}
}
loadStyleSheet("component.css","applyCSS");
You can see we've got one additional function in there now, this is simply the callback function which we've assigned when loading our external Style Sheet. It stores the returned CSS object in a variable and calls the cssToComponent function to apply the styles to a component (in this case a ComboBox component with instancename “myCombo”).
The example above uses a single component instance to apply the styles to. To do this for the component class and the _global.styles scope, all you need to do is change a bit of code in the callback function.
Assigning external CSS styles to the component class
_global.styles.ComboBox = new mx.styles.CSSStyleDeclaration();
cssToComponent(_global.styles.ComboBox,"myCSS","myCombo");
Using the code above in the callback function will make all instances of the ComboBox component subscribe to the styles you've assigned them.
Assigning external CSS styles to the _global.style scope
cssToComponent(_global.style,"myCSS","myCombo");
Using the code above in the callback function will apply your external styles to all UI components.
That about wraps up using styles on Flash MX 2004 Components. The next thing this tutorial will cover is the use of Themes to customize the actual assets of components.
Using Themes in Flash MX 2004
Themes are a collection of Styles and skins stored in a separate FLA file. Flash MX 2004 comes with two themes, the default Halo theme (HaloTheme.fla) and a Sample theme (SampleTheme.fla). The sample theme makes use of the complete set of available Styles.
Because the built-in components with Flash MX 2004 are now compiled (as SWC files), you are no longer able to edit its assets directly in your Flash project. You'll need to modify and apply a theme to make changes to your components' appearances.
At first, having to modify component assets outside of your Flash project may look like a bit of a hassle but it's actually a much cleaner and easily reusable method of skinning components.
While the Styles we discussed allow you to tweak color, font and other properties, Themes provide you with the ability to go in and edit the actual movieclip assets that a component uses.
We'll start out this section by looking at how to apply a theme to your Flash project.
Applying a theme to your project
- Start by creating a new FLA and drag an instance of the ComboBox, ScrollPane and DateField component on Stage.
- Go to File -> Import -> Open external library to import the the Sample theme (SampleTheme.fla) located in the following folder starting from your Flash MX 2004 installation directory:
- Windows: First Run\ComponentFLA
- Macintosh: First Run/ComponentFLA
- When you select this file and click on OK, the folder for SampleTheme.fla will pop up in your Library. Notice the following folder structure in Sample theme library: Flash UI components 2 -> Themes -> MMDefault. That last MMDefault folder itself contains a folder for each of the Flash MX 2004 UI components.
- Drag the “ComboBox Assets”,”ScrollPane Assets” and “DateField Assets” folders from the sample Theme library to the stage of our newly created FLA.
You'll notice that the live previews of your components don't change but, if you test your movie, you'll see that the components now have the Sample theme assets applied.
You can safely the delete the assets from the Stage, once you've dragged them into your project they are loaded into the library.
A good thing to know is that, once you've got the component assets from a Theme FLA loaded into your project, you can edit the assets from within your own Flash document. I would however advise you not to do so and keep the changes in the external theme FLA. The reason for this is that in many cases you end up making multiple FLAs for the same project and you don't want to be searching through all those files trying to locate that one particular changed skin you need.
Creating your own custom theme
Of course, you are not limited to using just the two themes that come with Flash MX 2004. Creating your own custom theme is not very difficult at all.
- Open up the SampleTheme.fla and immediately save it under a different name. For this tutorial we'll name it “myTheme.fla” (how original).
- The next step is pretty predictable:Go into the Library of “myTheme.fla” and edit all assets for the component you want to change. Once you've finished with that you can save the file and try to apply it to a new Flash document (see the section, above, on “Applying a theme”).
One thing to make sure is that you delete all component asset folders that you haven't customized in your theme FLA. That way you can be certain that you don't apply any of the Sample theme skins by accident.
Conclusion
You probably noticed by now that using Styles and Themes gives you some powerful tools for skinning Flash MX 2004 UI Components.
In this tutorial you learned how to set Style properties on single component instances, a component class and the _global scope. You' also learned how to create your own custom Style definition and had an introduction to how to apply and create themes in Flash MX 2004.
Now it's time to put the theory into practice, play around with the new features and drop me a line when you create something worth sharing. I'm sure we'll be seeing many wonderful and creative Flash MX 2004 themes out there in the not-too-distant future.
|