Adobe
Products
Acrobat
Creative Cloud
Creative Suite
Digital Marketing Suite
Digital Publishing Suite
Elements
Photoshop
Touch Apps
Student and Teacher Editions
More products
Solutions
Creative tools for business
Digital marketing
Digital media
Education
Financial services
Government
Web Experience Management
More solutions
Learning Help Downloads Company
Buy
Home use for personal and home office
Education for students, educators, and staff
Business for small and medium businesses
Licensing programs for businesses, schools, and government
Special offers
Search
 
Info Sign in
Welcome,
My cart
My orders My Adobe
My Adobe
My orders
My information
My preferences
My products and services
Sign out
Why sign in? Sign in to manage your account and access trial downloads, product extensions, community areas, and more.
Adobe
Products Sections Buy   Search  
Solutions Company
Help Learning
Sign in Sign out My orders My Adobe
Preorder Estimated Availability Date. Your credit card will not be charged until the product is shipped. Estimated availability date is subject to change. Preorder Estimated Availability Date. Your credit card will not be charged until the product is ready to download. Estimated availability date is subject to change.
Qty:
Purchase requires verification of academic eligibility
Subtotal
Review and Checkout
Adobe Developer Connection / Flex Developer Center /

Skinning a Flex 4 desktop application with MXML graphics

by David Gassner

David Gassner
  • www.bardotech.com

Content

  • Creating a custom skin component for an Adobe AIR application
  • Drawing vector-based graphics with MXML
  • Using optional skin parts

Created

22 March 2010

Page tools

Share on Facebook
Share on Twitter
Share on LinkedIn
Bookmark
Print
design Flex FXG skinning

Requirements

Prerequisite knowledge

A basic understanding of creating applications in Flash Builder and Flex is recommended.

User level

All

Required products

  • Flash Builder (Download trial)

Sample files

  • appskin_starter.zip (454 KB)
  • appskin_solution.zip (455 KB)

The Flex 4 SDK introduces new programming tools that make it easier than ever before to define the visual presentation of your web and desktop applications. These tools include a new skinning architecture that lets you define reusable skin components, which can be applied to applications and components both during compilation and at runtime. The skinning architecture is based on a new class named Skin, and a subclass named SparkSkin.

Once you configure an application or component to use one of these new skins, you can use traditional graphic files in JPG,.jpg,.jpg or SWF format to define the application or component’s look, or you can use new ActionScript classes that are included in the Flex 4 SDK that, when declared with MXML, mimic the syntax of the new FXG language – an XML-based language that defines low-level graphics, which are then rendered by Flash Player.

In this tutorial, I’ll show you how to create a great-looking desktop application that can be deployed with Adobe AIR. You’ll complete the following tasks:

  • Create a skin component suitable for use with the new Spark version of the WindowedApplication component
  • Bind the AIR application to the new skin at compilation time
  • Add MXML graphics to the skin to create a scalable application background image
  • Implement an optional skin part that displays the value of the WindowedApplication component’s status property

Creating a custom skin component for an Adobe AIR application

To get started with this tutorial, download and unzip the sample files and then follow these steps to import the starter project into Flash Builder 4:

  1. Choose File > Import Flex Project (FXP)
  2. In the Import Flash Builder Project dialog box, browse and select the appskin_starter.fxp file (see Figure 1).
Importing a Flex project in Flash Builder 4.
Figure 1. Importing a Flex project in Flash Builder 4.
  1. Click Finish to import the project.
  2. In the Package Explorer view, open the src folder’s default package and open the main application file, PhotoGallery.mxml (see Figure 2).
The Flash Builder 4 Package Explorer view, opened to the default package.
Figure 2. The Flash Builder 4 Package Explorer view, opened to the default package.

The main application file’s code is very simple; it uses the VerticalLayout class to define its layout and includes instances of the Spark Label and a custom SlideShow component:

<?xml version="1.0" encoding="utf-8"?> <s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:view="view.*" title="AIR Photo Gallery" width="800" height="600"> <s:layout> <s:VerticalLayout horizontalAlign="center" paddingTop="80"/> </s:layout> <s:Label text="My Photo Gallery" fontSize="24"/> <view:SlideShow/> </s:WindowedApplication>
  1. Choose Run > PhotoGallery to run the application.

    The application has a very simple appearance, with no custom styles or background graphics (see Figure 3). As each photo is displayed, its caption is shown below the photo, and the place where the photo was taken is shown in the status bar at the bottom of the application.

The sample application in its default state, without a custom skin.
Figure 3. The sample application in its default state, without a custom skin.
  1. Close the application and return to Flash Builder 4.

The application uses a custom component, SlideShow.mxml, that retrieves data from an XML file and displays photos one at a time using a Timer object and Fade effects. Next you’ll explore its code and functionality.

  1. Open SlideShow.mxml and its associated ActionScript file, slideShowScript.as, from the project’s view folder.
  2. Explore the code in these two files to see how the custom component loads data from an XML file, cycles through an ArrayList of photo data, displays photos and captions within binding expressions, and changes the application’s status property when a timer event is dispatched from a Timer object.

Note: You won’t make any changes to the SlideShow component or its associated ActionScript file in this tutorial. It’s designed as an encapsulated black box component that includes everything it needs to acquire and display data.

Creating a custom application skin

When you create a new Flex 4 desktop application in Flash Builder 4, the main application file uses <s:WindowedApplication> as its root element (and therefore as the application’s superclass). You can provide a custom skin for the application by creating a custom component subclassed from the new SparkSkin class. Skin components are typically defined in MXML, with ActionScript code added where required.

Follow these steps to create a new custom skin component:

  1. Return to the main application file, PhotoGallery.mxml.
  2. Click Design above the editing area to view the application in Design mode.
  3. Right-click on the application background (or Ctrl-click on Mac) and choose Create Skin.
  4. In the New MXML Skin dialog box, set the Package to skins (see Figure 4).
Creating a new custom skin component.
Figure 4. Creating a new custom skin component.
  1. Set the new components Name to CustomAppSkin.
  2. Check the option to Remove ActionScript Styling Code.
  3. Click Finish to create the new skin component.

The new MXML skin component is a copy of the WindowedApplication component’s default skin, spark.skins.spark.WindowedApplicationSkin. After the initial comments in the code, the start tag for the component’s root element looks like this:

<s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:fb="http://ns.adobe.com/flashbuilder/2009" alpha.disabledGroup="0.5" >

The MXML skin component is a subclass of SparkSkin. Notice that in addition to the usual XML namespaces that are added to all MXML applications and components, Flash Builder includes a namespace with an fb prefix.

Understanding the [HostComponent] metadata tag

The new skin component is specifically designed for use with the desktop application’s WindowedApplication component. Its [HostComponent] metadata tag defines a link between the component hosting a skin class and the skin class itself. The following declaration is placed in the new MXML skin component just after the starting <s:SparkSkin> tag:

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

The [HostComponent] metadata tag makes it possible to bind to any of the component’s property values with the expression hostComponent.[propertyName]. For a Button control, for example, you could use a Label control to output the value of the button’s label property:

<s:Label text="{hostComponent.label}"/>

Exploring skin states

Spark components can define one or more skin states. Each of these states must be declared within the custom skin component that you’ll use to skin your application. You can find out which skin states are required by a component by looking at its API documentation.

  1. Open PhotoGallery.mxml in Flash Builder 4 and look at the file in Source view.
  2. Click anywhere in the WindowedApplication tag.
  3. Press Shift+F2 to open context-sensitive help for the WindowedApplication class.
  4. At the top right of the documentation page click Skin States (see Figure 5).
The Skin States link at the top of the documentation page.
Figure 5. The Skin States link at the top of the documentation page.

As shown in Figure 6, the WindowedApplication class defines the following required skin states:

  • normal
  • disabled
  • normalAndInactive
  • disabledAndInactive
The list of required skin states for the WindowedApplication component.
Figure 6. The list of required skin states for the WindowedApplication component.

Now you’ll review the required skin states in the custom skin component:

  1. Open CustomAppSkin.mxml.
  2. Below the <fx:Script> tags, locate the <s:states> tag set.
  3. The MXML skin’s states match the requirements of the WindowedApplication component, and assign some of the states to state groups:
<s:states> <s:State name="normal" /> <s:State name="disabled" stateGroups="disabledGroup" /> <s:State name="normalAndInactive" stateGroups="inactiveGroup" /> <s:State name="disabledAndInactive" stateGroups="disabledGroup, inactiveGroup" /> </s:states>

Note: You must define the required skin states even if you don’t use them to modify the appearance of the application. If you forget to define the skin states, you’ll get a runtime error when you run the application.

Defining the default content group

The Spark Application and WindowedApplication components define a property named contentGroup, with a required data type of Group. When you declare visual objects in your main application file, they’re automatically added to the contentGroup container as the application starts up. When you use a custom skin component, you must define the group in the skin and assign it the contentGroup id. The component framework then knows where to place the visual objects that are defined in the main application file.

  1. With CustomAppSkin.mxml still open, delete all of the code after the <s:states> element, but be sure to keep the closing </s:SparkSkin> tag.
  2. Add a Group component with an id of contentGroup. Set its horizontalCenter property to 0 and its top property to 170:
<s:Group id="contentGroup" horizontalCenter="0" top="170"/>
  1. Create a new <s:Label> tag above the <s:Group id="contentGroup"…> tag and set its text property to "My Photo Gallery".
  2. Set the Label component’s fontSize to 48, top to 20, horizontalCenter to 0, and fontFamily to Papyrus:
<s:Label text="My Photo Gallery" fontSize="48" top="50" horizontalCenter="0" fontFamily="Papyrus"/>

Note: I’ve used the Papyrus font because it’s a fancy font that’s available on both Windows and Mac OS X. You can use any font you like.

  1. Save your changes.

Attaching the skin to the application

Your Spark skin component now is much simpler than the original skin, but is still compatible with the WindowedApplication component. When you created the new MXML skin component, Flash Builder added code to the application to attach (or bind) the skin to the application during compilation. Follow these steps to see the changes:

  1. Open PhotoGallery.mxml.
  2. Notice that a new skinClass attribute has been added to the starting <s:WindowedApplication> tag, with its value set to the package and class name of your new custom skin component:
skinClass="skins.CustomAppSkin"
  1. Delete or comment out the application’s <s:layout> tag set.
  2. Delete or comment out the application’s <s:Label> tag that creates the headline text above the slide show.

    The application code should now contain only the custom <view:SlideShow> component:

<?xml version="1.0" encoding="utf-8"?> <s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:view="view.*" title="AIR Photo Gallery" width="800" height="600" skinClass="skins.CustomAppSkin"> <view:SlideShow/> </s:WindowedApplication>
  1. Run the application.

    At this point, the application looks nearly the same as before, but without the status bar at the bottom of the screen.

  2. Close the application and return to Flash Builder 4.

The application’s heading label appears above the slide show component, even though it isn’t declared in the main application file (see Figure 7). You can follow the same pattern of adding text and graphic elements to the skin to further affect the application’s visual appearance.

The application with a new custom skin component. The headline label is now part of the custom skin.
Figure 7. The application with a new custom skin component. The headline label is now part of the custom skin.

Drawing vector-based graphics with MXML

You can add vector-based graphics to a Flex 4 application with ActionScript classes that are part of the new version of MXML. MXML supports use of the following primitive graphic objects:

  • Rect: a rectangle
  • Ellipse: an ellipse
  • Line: a line
  • Path: a filled graphic element that draws a series of segments

Each of these is represented in the Flex 4 SDK as an ActionScript class in the spark.primitives package. For example, the following code draws an ellipse that’s 200 pixels wide by 100 pixels high with a red fill color:

<s:Ellipse width="200" height="100"> <s:fill> <s:SolidColor color="#FF0000"/> </s:fill> </s:Ellipse>

In the preceding code, the Ellipse object’s fill property is set to an instance of the SolidColor class, with its color attribute set to red using hexadecimal notation. Figure 8 shows the resulting red ellipse.

A red ellipse drawn with MXML code.
Figure 8. A red ellipse drawn with MXML code.

You’ll first add a background color to the application’s custom skin by drawing a rectangle with a solid color that fills the application’s entire width and height. You’ll then layer another rectangle that creates a frame-like appearance on top of the first.

  1. Open CustomAppSkin.mxml.
  2. Add the following code after the skin states and before the Label control, to draw a rectangle with its width and height set to 100%. The fill is set to a SolidColor object with a color of #d7d5c4:
<s:Rect width="100%" height="100%"> <s:fill> <s:SolidColor color="#d7d5c4"/> </s:fill> </s:Rect>

Note: The application uses basic layout, similar to Flex 3’s absolute layout. Objects declared first in the MXML code are first in the application’s display list, and therefore are placed in the background. Objects declared later in the code are in the foreground.

  1. Run the application. Its background should now show the selected color.
  2. Close the application and return to Flash Builder 4.

    Next, you’ll add another vector graphic that creates a centered background graphic with rounded corners.

  3. Add the following code after the first rectangle, and before the Label that displays the application headline:
<s:Rect horizontalCenter="0" verticalCenter="0" width="{this.width-40}" height="{this.height-40}" radiusX="20" radiusY="20"> <s:fill> <s:SolidColor color="#f7f8f5"/> </s:fill> </s:Rect>

The new rectangle leaves an outer region showing the underlying background color, and has rounded corners.

  1. Run the application again.

    The new nested rectangle with rounded corners should be centered on the screen, displayed behind the slide show component.

  2. Close the application and return to Flash Builder 4.
  3. Add a filters property to the last rectangle object that implements a drop shadow with an angle of 90 degrees, a color of #333333, and other properties to fine-tune its appearance. The new version of the rectangle code should now look like this:
<s:Rect horizontalCenter="0" verticalCenter="0" width="{this.width-40}" height="{this.height-40}" radiusX="20" radiusY="20"> <s:fill> <s:SolidColor color="#f7f8f5"/> </s:fill> <s:filters> <s:DropShadowFilter angle="90" color="#333333" distance="7" alpha="0.65" quality="4"/> </s:filters> </s:Rect>
  1. Run the application again.

As shown in Figure 9, the nested rectangle will now display a bottom drop shadow.

The application with a complete custom skin.
Figure 9. The application with a complete custom skin.

Your skin is nearly complete, and the application has a very different appearance than it did previously.

Using optional skin parts

Spark components such as WindowedApplication can declare optional skin parts. If these skin parts are declared in your custom skin, the host component will already know what to do with them. You can find out which optional skin parts are supported by a component by looking at its documentation.

  1. Look once more at the documentation for the WindowedApplication class.

    Note: You can again use context-sensitive help, as described in the previous section of this tutorial.

  2. This time click Skin Parts (not Skin States) at the top right of the documentation page.

The WindowedApplication component supports the following skin parts (see Figure 10):

  • contentGroup:Group
  • controlBarGroup:Group
  • gripper:Button
  • statusBar: IVisualElement
  • statusText: TextBase
  • titleBar: TitleBar
The Skin Parts documentation for the WindowedApplication class.
Figure 10. The Skin Parts documentation for the WindowedApplication class.

You can implement any of the optional skin parts in your custom skin by declaring an object of the required type and assigning it the id of the skin part as declared in the host component. For example, if you wanted to provide a custom gripper object that the user could click and drag to resize the application, the Button object in the custom skin component might look like this:

<s:Button id="gripper"/>

Any properties, styles or skins you apply to the Button object would determine its appearance, but the host component would react to the button’s events (such as click, mouseDown and mouseMove) just like it does with its default gripper object.

In the following steps, you’ll add a statusText control to the custom application skin. Then, when you set the application’s status property, the statusText control will automatically show the property’s value.

  1. Open CustomAppSkin.mxml.
  2. At the bottom of the component code, just before the ending </s:SparkSkin> tag, add the following code to create a status bar with a blurred outline, and a status text control with custom font styles:
<s:Group id="statusBar" horizontalCenter="0" bottom="50" width="200"> <s:Rect width="100%" height="30"> <s:fill> <s:SolidColor color="#a78d84"/> </s:fill> <s:filters> <s:BlurFilter blurX="20" blurY="20"/> </s:filters> </s:Rect> <s:Label id="statusText" horizontalCenter="0" verticalCenter="0" fontFamily="Papyrus" fontWeight="bold" color="#000000" fontSize="18"/> </s:Group>

Notice that the Label control has an id of statusText, matching the id of the WindowedApplication component’s optional skin part.

  1. Run the application again.

Now, each time the photo is updated in the slide show component, the statusText object will show the value of the application’s status property (see Figure 11).

A completed application using the WindowedApplication component’s status property and statusText  skin part.
Figure 11. A completed application using the WindowedApplication component’s status property and statusText skin part.

The completed custom skin component code looks like this:

<s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:fb="http://ns.adobe.com/flashbuilder/2009" alpha.disabledGroup="0.5" > <fx:Metadata> [HostComponent("spark.components.WindowedApplication")] </fx:Metadata> <s:states> <s:State name="normal" /> <s:State name="disabled" stateGroups="disabledGroup" /> <s:State name="normalAndInactive" stateGroups="inactiveGroup" /> <s:State name="disabledAndInactive" stateGroups="disabledGroup, inactiveGroup" /> </s:states> <s:Rect width="100%" height="100%"> <s:fill> <s:SolidColor color="#d7d5c4"/> </s:fill> </s:Rect> <s:Rect horizontalCenter="0" verticalCenter="0" width="{this.width-40}" height="{this.height-40}" radiusX="20" radiusY="20"> <s:fill> <s:SolidColor color="#f7f8f5"/> </s:fill> <s:filters> <s:DropShadowFilter angle="90" color="#333333" distance="7" alpha="0.65" quality="4"/> </s:filters> </s:Rect> <s:Label text="My Photo Gallery" fontSize="48" top="50" horizontalCenter="0" fontFamily="Papyrus"/> <s:Group id="contentGroup" horizontalCenter="0" top="170"/> <s:Group id="statusBar" horizontalCenter="0" bottom="50" width="200"> <s:Rect width="100%" height="30"> <s:fill> <s:SolidColor color="#a78d84"/> </s:fill> <s:filters> <s:BlurFilter blurX="20" blurY="20"/> </s:filters> </s:Rect> <s:Label id="statusText" horizontalCenter="0" verticalCenter="0" fontFamily="Papyrus" fontWeight="bold" color="#000000" fontSize="18"/> </s:Group> </s:SparkSkin>

Where to go from here

In this tutorial you learned how to create and apply a custom skin component for the Flex 4 WindowedApplication component. You can learn more about FXG graphics and custom component skinning from the Flex 4 documentation:

  • Flash XML Graphics (FXG) and MXML graphics
  • Using FXG in applications built with Flex
  • Creating Spark Skins

And be sure to visit the Flex Developer Center for more helpful tips and tutorials.

More Like This

  • Providing XML to controls with E4X
  • Graphical skinning with Flex
  • Designing Flex 3 skins and styles using Creative Suite 3 and Flex Builder 3
  • Foundation Flex for Designers excerpt: Flex Builder and Flash
  • AdvancED Flex 3 excerpt: Sculpting interactive business intelligence interfaces
  • Managing application state with Flex 3
  • Flex 3 in Action book excerpt: Introduction to pop-ups
  • Using Flex styles
  • Flex mobile skins – Part 3: Multiplatform development
  • Migrating Flex 3 applications to Flex 4 – Part 2: Beginning migration of the Dashboard application to Flex 4

Tutorials & Samples

Tutorials

  • Flex mobile performance checklist
  • Flex and Maven with Flexmojos – Part 3: Journeyman
  • Migrating Flex 3 applications to Flex 4.5 – Part 4

Samples

  • Twitter Trends
  • Flex 4.5 reference applications
  • Mobile Trader Flex app on Android Market

Flex User Forum

More
07/25/2011 Flash Player Debug Issues - Safari 5.1 & Chrome 13
04/22/2012 Loader png - wrong color values in BitmapData
04/22/2012 HTTPService and crossdomain.xml doesn't work as expected
04/23/2012 Memory related crashes in Flex application

Flex Cookbook

More
04/06/2012 How to detect screen resize with a SkinnableComponent
02/29/2012 Embed Stage3D content inside Flex application components
02/15/2012 Custom WorkFlow Component
02/09/2012 Using Camera with a MediaContainer instead of VideoDisplay

Products

  • Acrobat
  • Creative Cloud
  • Creative Suite
  • Digital Marketing Suite
  • Digital Publishing Suite
  • Elements
  • Mobile Apps
  • Photoshop
  • Touch Apps
  • Student and Teacher Editions

Solutions

  • Digital marketing
  • Digital media
  • Web Experience Management

Industries

  • Education
  • Financial services
  • Government

Help

  • Product help centers
  • Orders and returns
  • Downloading and installing
  • My Adobe

Learning

  • Adobe Developer Connection
  • Adobe TV
  • Training and certification
  • Forums
  • Design Center

Ways to buy

  • For personal and home office
  • For students, educators, and staff
  • For small and medium businesses
  • For businesses, schools, and government
  • Special offers

Downloads

  • Adobe Reader
  • Adobe Flash Player
  • Adobe AIR
  • Adobe Shockwave Player

Company

  • News room
  • Partner programs
  • Corporate social responsibility
  • Career opportunities
  • Investor Relations
  • Events
  • Legal
  • Security
  • Contact Adobe
Choose your region United States (Change)
Choose your region Close

North America

Europe, Middle East and Africa

Asia Pacific

  • Canada - English
  • Canada - Français
  • Latinoamérica
  • México
  • United States

South America

  • Brasil
  • Africa - English
  • Österreich - Deutsch
  • Belgium - English
  • Belgique - Français
  • België - Nederlands
  • България
  • Hrvatska
  • Česká republika
  • Danmark
  • Eastern Europe - English
  • Eesti
  • Suomi
  • France
  • Deutschland
  • Magyarország
  • Ireland
  • Israel - English
  • ישראל - עברית
  • Italia
  • Latvija
  • Lietuva
  • Luxembourg - Deutsch
  • Luxembourg - English
  • Luxembourg - Français
  • الشرق الأوسط وشمال أفريقيا - اللغة العربية
  • Middle East and North Africa - English
  • Moyen-Orient et Afrique du Nord - Français
  • Nederland
  • Norge
  • Polska
  • Portugal
  • România
  • Россия
  • Srbija
  • Slovensko
  • Slovenija
  • España
  • Sverige
  • Schweiz - Deutsch
  • Suisse - Français
  • Svizzera - Italiano
  • Türkiye
  • Україна
  • United Kingdom
  • Australia
  • 中国
  • 中國香港特別行政區
  • Hong Kong S.A.R. of China
  • India - English
  • 日本
  • 한국
  • New Zealand
  • 台灣

Southeast Asia

  • Includes Indonesia, Malaysia, Philippines, Singapore, Thailand, and Vietnam - English

Copyright © 2012 Adobe Systems Incorporated. All rights reserved.

Terms of Use | Privacy Policy and Cookies (Updated)

Ad Choices

Reviewed by TRUSTe: site privacy statement