Beginner’s Guide to Skinning your Flex 4 Application or AIR Application

While working on the Tour de Flex samples for Flex 4, I spent some time digging into the new Flex 4 Skinning Architecture and found that I could do some really cool stuff with it. Though I’m definitely NOT a designer, I was impressed by the level of control it offered me and wanted to share some basics/tips for skinning your Flex/AIR applications.

So you want to skin your app… where do you start?

1) Copy the source code for the default ApplicationSkin.mxml or WindowedApplicationSkin.mxml file from the Flex 4 SDK source into a new MXML component file within your project. The path should be something like: /<your-flex4-sdk-folder>/frameworks/projects/spark/src/spark/skins/spark/ (or on Windows it would be c:\..\<your-flex4-sdk-folder>\frameworks\projects\spark\src\spark\skins\spark\). You can also use the default skins specified in the Wireframe Flex 4 theme included in the SDK. They are sometimes simpler to work with (for more info on Flex 4 themes, see this link). The path to the wireframe skins will be something like: /<your-flex4-sdk-folder>/frameworks/projects/wireframe/src/spark/skins/wireframe/ (or on Windows it would be c:\..\<your-flex4-sdk-folder>\frameworks\projects\wireframe\src\spark\skins\wireframe\)

I figure what better way to make sure you have control over every detail than by starting with the Flex 4 SDK default skin class currently being used by the container or component. Many times you will not need that level of control and can omit parts of the code that are not changing, however I personally found it nice to see the options I had for modifying skin parts and the fact that they included comments in their skins to explain what each part is.

This is a quick and easy way to understand specifically which skin parts are defined as well. You can also check the Adobe Flex 4 Livedocs for that particular host component’s class documentation to see the required skin parts, skin states etc. Generally though I begin by just grabbing the skin source for the host component I want to skin and modifying or omitting different parts to see how it affected the component (so in the case of skinning an app I would look for either spark.components.ApplicationSkin.mxml or spark.components.WindowedApplication.mxml respectively).

Note: ‘host component’ simply refers to the Spark component/container I want to skin.

2) Change the parts you want to control. So for an Application you may want to modify the ApplicationControlBar look in addition to the background. This can all be done by modifying the source code for the ApplicationSkin.mxml class. Just rename it and modify it to your liking. These examples do not go into skinning the ApplicationControlBar, but you can apply the information from this post in doing so.

Quick Tip: if you just want to use a graphic for your application background, you could use a skin as simple as this:

<?xml version="1.0" encoding="utf-8"?>
<s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009"
   xmlns:mx="library://ns.adobe.com/flex/halo"
   xmlns:s="library://ns.adobe.com/flex/spark">;

    <fx:Metadata>
        [HostComponent("spark.components.Application")]
    </fx:Metadata>

    <s:states>
        <s:State name="normal" />
        <s:State name="disabled" />
    </s:states>

    <s:BitmapImage width="400" height="500" source="@Embed('assets/SampleBackground.png')"/>
    <s:Group id="contentGroup" left="0" right="0" top="0" bottom="0">
</s:SparkSkin>

Note: You must keep the ‘contentGroup’ part in your custom skin so the content of your application shows, otherwise you will only see your image. In the case of skinning an Application, the actual Application.mxml Livedocs will show you which skin parts are required. Scroll down until you see the section labeled Skin Parts in the class documentation. You can also view the inherited skin parts and skin states there.

If you want your image to actually fill in the entire space of the app, then you could use something like this:

<?xml version="1.0" encoding="utf-8"?>
<s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009"
 xmlns:mx="library://ns.adobe.com/flex/halo"
 xmlns:s="library://ns.adobe.com/flex/spark">

 <fx:Metadata>
     [HostComponent("spark.components.Application")]
 </fx:Metadata>

 <s:states>
     <s:State name="normal" />
     <s:State name="disabled" />
 </s:states>

 <s:Rect id="backgroundRect" left="0" right="0" top="0" bottom="0">
     <s:fill>
         <s:BitmapFill source="@Embed('assets/SampleBackground.png')"/>
     </s:fill>
 </s:Rect>

 <s:Group id="contentGroup" left="0" right="0" top="0" bottom="0" />
</s:SparkSkin>

3) Apply the custom skin to your MXML application. You can do this in two ways, either inline MXML or CSS. For inline MXML, you simply set the skinClass property on the root Application tag to the fully-qualified name of your custom class. For instance:

    <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark"
       xmlns:mx="library://ns.adobe.com/flex/halo
       skinClass="skins.CustomApplicationSkin">

In CSS it would be something like:

s|Application
{
    skinClass: ClassReference("com.devgirl.blogexample.skins.CustomApplicationSkin");
}

I generally use the skinClass property for application skins. The CSS way to do it is nice when you want to apply a certain skin to all instances of a component that you may have created a custom class for, such as Button for example.

Below are a couple of examples of skinning an application with a simple custom application skin (keeping in mind the fact that I am so NOT a designer ;)) but, they should help give an idea of what you are able to do. The screenshot is shown first followed by the source code for the custom skin and Flex app:

Picture 5

The custom background skin for the above screenshot looks like:

<?xml version="1.0" encoding="utf-8"?>
<!-- ../skins/BackgroundImageAppSkin.mxml>
<s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009" 
		xmlns:mx="library://ns.adobe.com/flex/halo" 
		xmlns:s="library://ns.adobe.com/flex/spark">
	
	<fx:Metadata>
		[HostComponent("spark.components.Application")]
	</fx:Metadata> 
	
	<s:states>
		<s:State name="normal" />
		<s:State name="disabled" />
	</s:states>
	
	<!-- This image fill also specifies padding around it -->
	<s:Rect id="backgroundRect" left="100" right="100" top="20" bottom="20">
		<s:fill>
			<s:BitmapFill source="@Embed('assets/wood-bg.png')"/>
		</s:fill>
	</s:Rect>	
	
	<s:Group id="contentGroup" left="0" right="0" top="0" bottom="0" />
</s:SparkSkin>

The Flex application code for this screenshot is the following:

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
			   xmlns:s="library://ns.adobe.com/flex/spark" 
			   xmlns:mx="library://ns.adobe.com/flex/halo" 
			   skinClass="skins.BackgroundImageAppSkin" 
			   backgroundColor="0x000000">
	
	<fx:Declarations/>
	
	<s:VGroup horizontalCenter="0" verticalCenter="0">
		<s:Label text="Wood Sales Int'l" fontSize="42" />
		<s:Border borderColor="0x000000" borderWeight="3" cornerRadius="7" horizontalCenter="0" verticalCenter="0">
			<s:VGroup>
				<mx:Form fontSize="16">
					<mx:FormItem label="Userid:">
						<s:TextInput id="userid"/>
					</mx:FormItem>
					<mx:FormItem label="Password:">
						<s:TextInput id="pw"/>
					</mx:FormItem>
					<mx:FormItem>
						<s:Button label="Login"/>
					</mx:FormItem>
				</mx:Form>
			</s:VGroup>
		</s:Border>
	</s:VGroup>
</s:Application>

Now I can change just one line in my sample code, the skinClass property to a different skin, and produce this:

Picture 7

And below is the custom gradient background skin for the above screenshot:

<?xml version="1.0" encoding="utf-8"?>
<s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009" 
		xmlns:mx="library://ns.adobe.com/flex/halo" 
		xmlns:s="library://ns.adobe.com/flex/spark">
	
	<fx:Metadata>
		[HostComponent("spark.components.Application")]
	</fx:Metadata> 
	
	<s:states>
		<s:State name="normal" />
		<s:State name="disabled" />
	</s:states>
	
	<!-- border -->
	<s:Rect left="10" right="10" top="10" bottom="10" radiusX="9" radiusY="9">
		<s:stroke>
			<mx:SolidColorStroke color="0xCCCCCC" alpha=".5" weight="4"/>
		</s:stroke>
	</s:Rect>

	<s:Rect id="backgroundRect" left="10" right="10" top="10" bottom="10" radiusX="9" radiusY="9">
		<s:fill>
			<s:LinearGradient rotation="90">
				<s:entries>
					<s:GradientEntry color="0x0000FF" ratio="0.00" alpha="0.8"/>
					<s:GradientEntry color="0x336699" ratio="1.0" alpha="0.5"/>
					<s:GradientEntry color="0xCCCCCC" ratio="0.5" alpha="0.8"/>
				</s:entries>
			</s:LinearGradient>	
		</s:fill>
	</s:Rect>
	
	<s:Group id="contentGroup" left="0" right="0" top="0" bottom="0" />
</s:SparkSkin>

Again, the sample Flex application MXML looks exactly the same except we are specifying my custom gradient background skin on the skinClass property:

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
			   xmlns:s="library://ns.adobe.com/flex/spark" 
			   xmlns:mx="library://ns.adobe.com/flex/halo" 
			   skinClass="skins.GradientBackgroundAppSkin">
	
	<fx:Declarations/>
	
	<s:VGroup horizontalCenter="0" verticalCenter="0">
		<s:Label text="Wood Sales Int'l" fontSize="42" />
		<s:Border borderColor="0x000000" borderWeight="3" cornerRadius="7" horizontalCenter="0" verticalCenter="0">
			<s:VGroup>
				<mx:Form fontSize="16">
					<mx:FormItem label="Userid:">
						<s:TextInput id="userid"/>
					</mx:FormItem>
					<mx:FormItem label="Password:">
						<s:TextInput id="pw"/>
					</mx:FormItem>
					<mx:FormItem>
						<s:Button label="Login"/>
					</mx:FormItem>
				</mx:Form>
			</s:VGroup>
		</s:Border>
	</s:VGroup>
</s:Application>

So you can see just how quickly you can make your application theme look entirely different with just a one line change and not modifying any behavioral logic. It’s very powerful and there are so many more things beyond this that you can do with the FXG drawing API’s.

A couple other tips for non-designer folks out there… You can use the Adobe CS4 products such as Photoshop, Illustrator and Fireworks etc to create your skins and then export them as FXG and use them within your skins. You do not have to understand all of the FXG classes and properties necessarily but can just visually draw what you want with those products and either do a ‘Save As’ .fxg extension type (such as in Photoshop), or use the Export to FXG command (from the Commands menu) in Fireworks. For instance, it may generate your FXG for a drawn border (using the Path FXG object) based on what you drew that you can use without having to figure all the specific points out. You can then extract the parts you want from the FXG and place them in your custom skin class. Many times you will also get an image as a result and will use that within your skin class as well, like I did in the wood sample above. The image is exported and referenced as part of the FXG from the CS4 tools. If you play around with it a bit and export the FXG to see what it created, you will quickly see what you can do.

Important to note: One FXG-related issue I ran into when exporting from Photoshop or Fireworks, is that there are times when what you produced will result in either a TextGraphic or BitmapGraphic in the FXG source and you must manually change them to RichText (for TextGraphic) and BitmapImage (for BitmapGraphic) or you will get compiler issues with the namespace. Detailed information about this can be found here.

Also, an obvious tip to most, but just in case it helps someone… When I create my new image, I always use the ‘Transparent’ background mode so that it fits in with whatever color scheme I might choose within the app. If you know exactly what color you are using already, you can set the background to that and it will matte it to that color. This is probably already known to many, but for those that might not know, it will save you time figuring out why there is a white border around your image in your app!

Also note, everything above can be applied to skinning your AIR applications as well. You simply start with the WindowedApplicationSkin.mxml default skin class from the Flex 4 SDK.

There’s so much to the skinning architecture to understand, that you should definitely check out the Flex 4 team blogs and Livedocs Help to complete your knowledge.

Advertisements

15 Responses to “Beginner’s Guide to Skinning your Flex 4 Application or AIR Application”

  1. Skinning Flex/AIR Applications…

    This tutorial will walk you through the basics of skinning your Flex or Air app from the very beginning. Very well done with plenty of code illustration. ……

  2. Hmmm Styling the WindowedApplication is not as easy as you describe when you wish to modify title bar and buttons.

    • Hi Fred, could you elaborate on the experience in case myself or anyone else could provide any assistance or for further reference for people? Thanks!! Holly

  3. Great post. I was wondering what owning Fireworks/Photoshop would do for and this is the first place that answered my question.

    • Hi Jake, Great, I’m so glad my post helped! That was actually one thing I really wanted to understand first as well with Flex 4. Particularly how I could use these tools together to be more productive. You will also want to check out Flash Catalyst for creating skins as well when it is released. Thanks! Holly

  4. I used to add lots of external illustrations and images to match the scheme of an application earlier, but i guess, this would definitely reduce the efforts provided i get familiar with skins.
    thanks a lot for information.
    regards

  5. VRy interesting to read it 😛

  6. Thats nice tute for skinning flex App’s
    i was just wondering if you know how do we change the default background color of a Flex 4 Application , if we dont specify any color it takes as white , i would rather want a transperant background than a white one,
    if i embed my flex app in a html page i would want the background to be the back ground of html page than a white background
    i tried setting wmode to tranperant but the white background never goes.
    i appreciate any help in this.

    Thanks,
    Lisa

  7. Great resource! It was very helpfull! The trick in skinning is remembering the ContentGroup…that is where I slipped up and had nothing displayed in my component.

  8. Hi,
    is there a way to design spark skins in fireworks or illustrator and export them for the usage in flash builder 4 ?

    btw. why aren’t you using flex for this blog here ?

    • Hi there, yes, you can design artwork in Illustrator and Fireworks CS4 and do either Save As or Export to FXG (depending on CS product you’re using), which you can then use in your custom skin classes. You can find a more detailed description of this here: http://ria.dzone.com/articles/spark-architecture-flex-4

      As far as this blog… I’m just using a standard wordpress blog, didn’t really seem like a true Flex use case 🙂

      Hope this helps!
      Holly

  9. I’m new to website development. Very little knowledge about Skinning & Flex too. I want Application control bar to be in a different shape. It should be horizontal at top. & a sort of side bar[vertical] in right side. How can I do this? I would like to how can I customize the Application Control Bar in Flex.
    Can I have more than two application Control Bar to get this design??

  10. Matthias ETIENNE Says:

    Very good post. Thanks for sharing !

  11. i was trying to use data binding to have my custom buttons assign the icon used in the skin, the moment they are created in the main mxml file. For example, i created an IconButton extends spark.components.Button, included only a myVar:String (and the getter and setter) and in the skin file – iconButtonSkin – i used hostComponent.myVar to access the value and display it through the label. In the main.mxml file i created the button simply : <myComponents:Icon Button myVar"blablabla". It did work for this simple proof of concept. But I cant get data binding in the skin to work for the source parameter of the s:BitampImage. The embeding is not working. Is it because of how the Embed tag works? Is there a work around for what i want to do?
    thank you in advance

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: