Table of contents
Skinning is the process of changing the appearance of a component by modifying or replacing its visual elements. These elements can be made up of images, SWF files, or class files that contain drawing API methods.
Skins define the visual appearance of parts or of entire components in various states. For example, a Button control has many skins, each representing a state for the button. Skins defined using the downSkin, upSkin, and overSkin style properties represent the way a button appears when it is down, up, and when the mouse is over the button.
There are several ways that you can define skins: inline, by using the setStyle() method, and by using Cascading Style Sheets (CSS). The various examples in this section demonstrate these methods.
You can add skins to a Flex component graphically and programmatically.
To use graphical skins, you embed image files in your Adobe® Flex™ application. Then you use these files as style properties that replace the existing skins of the component.
The main advantage of graphical skinning is that designers can use visual tools like Adobe Photoshop to create component skins without any knowledge of ActionScript.
Graphical skins may, however, take up more memory than programmatic skins because they require external image or SWF files that are embedded in the final SWF file of the Flex application.
Tip: If you change the graphics files that comprise one or more skins, you must recompile your Flex application for the changes to take effect.
Flex wraps embedded images in a class. Therefore, when you apply skins as style properties, you should think of each skin as a class. If you set the value of the upSkin property of a Button control (for example, to "myimage.jpg"), you are really changing the reference from the current skin class to this new class.
The following example uses a CSS type selector to set the upSkin, overSkin and downSkin style properties of all Button controls to use external PNG images.
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" viewSourceURL="src/SkinningGraphical1/index.html" layout="horizontal" width="270" height="100" horizontalAlign="center" verticalAlign="middle" > <mx:Style> Button { upSkin: Embed("assets/box_closed.png"); overSkin: Embed("assets/box.png"); downSkin: Embed("assets/box_new.png"); } </mx:Style> <mx:Button/> <mx:Text text="Roll over and click the box!"/> </mx:Application>
To view the full source, right-click the Flex application and select View Source from the context menu.
One drawback to embedding images as skins is that they can become distorted if you resize the component that uses the skin. You can use a technique called 9-slice scaling to create skins that do not become distorted when the component is resized.
Using the 9-slice scaling feature, the four corners of your image do not scale at all, the horizontal border scales only in the horizontal direction, and the vertical border scales only in the vertical direction.
Link: For information on the 9-slice scaling technique, see Embedding images that scale with 9-slice scaling in the Embedding Assets topic.
This example uses the scaleGridTop, scaleGridBottom, scaleGridLeft and scaleGridRight grid-line location properties in CSS to define the 9-slice scaling grid for the background image of a VBox component. You can make a background-image scale to fill the whole component by setting the background-size CSS property to "100%". To illustrate the differences between 9-slice scaling and regular scaling, the example contains a second VBox that has the background image that is embedded without using 9-slice scaling.
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" viewSourceURL="src/SkinningGraphical2/index.html" layout="vertical" width="525" height="500" > <mx:Style> .nineSliceScalingBackground { background-image: Embed("assets/fancy_background.png", scaleGridTop="55", scaleGridBottom="137", scaleGridLeft="57", scaleGridRight="266"); background-size:"100%"; } .nonNineSliceScalingBackground { background-image:Embed("assets/fancy_background.png"); background-size:"100%"; } VBox { padding-bottom:50; padding-top:50; padding-left:60; padding-right:60; } </mx:Style> <mx:VBox styleName="nineSliceScalingBackground" width="100%" height="50%"> <mx:Text width="100%" text="This VBox has a graphical 9-slice scaling background skin that stretches to fill the background.{'\r\r'}Notice how the corners do not scale. You can also use a preset padding value to offset your content so it appears inside the borders of the background image." /> </mx:VBox> <mx:VBox styleName="nonNineSliceScalingBackground" width="100%" height="50%"> <mx:Text width="100%" text="This VBox, on the other hand, does not use 9-slice scaling for its background image. Notice how the image is uniformly scaled, resulting in aliasing. {'\r\r'}Also, notice how this text overlaps the background as the corners do not have fixed dimensions that we can compensate for by using padding." /> </mx:VBox> </mx:Application>
To view the full source, right-click the Flex application and select View Source from the context menu.
You draw programmatic skins by using ActionScript statements that define these skins in class files. To change the appearance of controls that use programmatic skins, you edit an ActionScript class file and compile it with your Flex application.
One advantage of programmatic skinning is that it provides you with a great deal of control over styles. For example, you cannot control the radius of a Button control's corners with style sheets or graphical skins, but you can by using programmatic skins. You can also develop programmatic skins directly in your Flex authoring environment or any text editor, without using a graphics tool such as Adobe® Flash®. Programmatic skins also tend to use less memory because they contain no external image files.
The disadvantage of programmatic skinning is that it requires a very high degree of ActionScript knowledge and requires a developer (instead of a designer) to create the skins or to translate a designer's designs to code. Using programmatic skinning in your applications only makes sense if the ability to style your components is important to your application.
Tip: A programmatic skin's class file must be in your Flex application's classpath when you compile your application.
The following example uses programmatic skinning to create a custom border skin. The CustomBorder class extends the base RectangularBorder class and inherits its drawRoundRect() method. This method originates in the ProgrammaticSkin class, which is the base class of all built-in Flex skins. Your skin classes can extend the ProgrammaticSkin class, or one of its subclasses like RectangularBorder, to inherit the higher-level drawing and utility methods.
ActionScript file
package { import mx.skins.RectangularBorder; import flash.display.Graphics; import mx.graphics.RectangularDropShadow; public class CustomBorder extends RectangularBorder { private var dropShadow:RectangularDropShadow; override protected function updateDisplayList (unscaledWidth:Number, unscaledHeight:Number):void { super.updateDisplayList(unscaledWidth, unscaledHeight); var cornerRadius:Number = getStyle("cornerRadius"); var backgroundColor:int = getStyle("backgroundColor"); var backgroundAlpha:Number = getStyle("backgroundAlpha"); graphics.clear(); // Background drawRoundRect ( 0, 0, unscaledWidth, unscaledHeight, {tl: 0, tr: cornerRadius, bl: cornerRadius, br: 0}, backgroundColor, backgroundAlpha ); // Shadow if (!dropShadow) dropShadow = new RectangularDropShadow(); dropShadow.distance = 8; dropShadow.angle = 45; dropShadow.color = 0; dropShadow.alpha = 0.4; dropShadow.tlRadius = 0; dropShadow.trRadius = cornerRadius; dropShadow.blRadius = cornerRadius; dropShadow.brRadius = 0; dropShadow.drawShadow(graphics, 0, 0, unscaledWidth, unscaledHeight); } } }
MXML file
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" viewSourceURL="src/ProgrammaticSkinning/index.html" > <mx:VBox borderSkin="CustomBorder" backgroundColor="0xCCCC99" backgroundAlpha="0.8" cornerRadius="14" paddingLeft="20" paddingTop="20" paddingRight="20" paddingBottom="20" > <mx:Text text="The VBox has a {'\r'}programmatic skin."/> </mx:VBox> </mx:Application>
To view the full source, right-click the Flex application and select View Source from the context menu.
Aral Balkan acts and sings, leads development teams, designs user experiences, architects rich Internet applications, and runs OSFlash.org, the London Macromedia User Group, and his company, Ariaware. He loves talking design patterns and writing for books and magazines. He also authored Arp, the open-source RIA framework for the Flash platform. Aral is generally quite opinionated, animated, and passionate. He loves to smile, and can even chew gum and walk at the same time.