Accessibility
Trilemtry

Trilemetry, Inc.

Created:
4 October 2009
User Level:
All
Products:
Flex

Exercise 3.5: Creating and applying skins

In this exercise, you will create a skin for the Employee Portal application and use the provided skinning components to configure the application so that it appears as shown in Figure 1. You will also learn how to create a custom skin property and reuse it to style Flex components.

This is the finished application.

Figure 1. Take stock of your tasks in this exercise.

In this exercise, you will learn how to:

Requirements

In order to complete this tutorial, you need the following software and files:

Flash Builder 4

Sample files:

Prerequisite knowledge

Creating a skin

In this section, you will use Flash Builder to create a skin for the Employee Portal application.

  1. Download the ex3_05_starter.zip file if you haven't done so already and extract the ex3_05_starter.fxp file to your computer.
  2. Open Flash Builder.
  3. Import the ex3_05_starter.fxp file.
  4. Within the Package Explorer, right-click the skins folder and select New > MXML Application (see Figure 2).

    Create a new MXML application.

    Figure 2. Create a new MXML application.

  5. In the New MXML Application dialog box, name the application ApplicationContainerSkin (see Figure 3).

    Name the application
ApplicationContainerSkin.

    Figure 3. Name the application ApplicationContainerSkin.

  6. Click Finish.

    The ApplicationContainerSkin.mxml file will open in the Editor.

  7. From the ApplicationContainerSkin.mxml file, delete the Declarations tag block.
  8. Replace the Application tags with SparkSkin tags:

    <s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009" 
       xmlns:s="library://ns.adobe.com/flex/spark" 
       xmlns:mx="library://ns.adobe.com/flex/halo" 
       minWidth="1024" minHeight="768">
    
    </s:SparkSkin>
  9. Between the SparkSkin tags, add a Metadata tag set:

    <s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009" 
       xmlns:s="library://ns.adobe.com/flex/spark" 
       xmlns:mx="library://ns.adobe.com/flex/halo" 
       minWidth="1024" minHeight="768">
     
        <fx:Metadata>
     
        </fx:Metadata>
        
    </s:SparkSkin>
  10. Between the Metadata tags, use the HostComponent() function to assign the spark.components.Application package to the skin:

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

    The HostComponent metadata tag identifies the host component of a Spark skin class. As a result of this definition, you can access the public members of the host component's instance from within the skin. In other words, in this case, you can access the properties of the Application tag.

  11. Below the Metadata tag block, add a states tag block:

    ...
        </fx:Metadata>
        
        <s:states>
             
        </s:states>
  12. Within the states block, add a State instance with the name property value assigned to normal:

    <s:states>
            
        <s:State name="normal"/>
            
    </s:states>
  13. Below the State instance, add another State instance with the name property value assigned to unused:

    <s:states>
            
        <s:State name="normal" />
        <s:State name="unused" />
          
    </s:states>
  14. Below the states block, add a Rect tag block:

     ...
    </s:states>
        
    <s:Rect>
         
    </s:Rect>
  15. Within the opening Rect tag, assign the width property value to 973, the height property value to 636, and the x and y property values to 0:

    <s:Rect width="973" height="636" x="0" y="0">
            
    </s:Rect>
  16. Between the Rect tags, add stroke property block:

    <s:Rect width="973" height="636" x="0" y="0">
            
        <s:stroke>
             
        </s:stroke>
               
    
    </s:Rect>
  17. Between the stroke tags, add a LinearGradientStroke instance with the weight property value assigned to 1:

    <s:stroke>           
    
        <s:LinearGradientStroke weight="1"/>        
    </s:stroke>
  18. Save the file.

Applying a skin

In this section you will apply the ApplicationContainerSkin component to the Employee Portal application.

  1. From the Package Explorer view, open the EmployeePortal.mxml file.
  2. Within the opening Application tag, assign the skinClass property value to skins.ApplicationContainerSkin:

    <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" 
       width="980" height="690"
       xmlns:components="components.*" 
       skinClass="skins.ApplicationContainerSkin">
  3. Save the file.
  4. Run the application.

You should the black outline of a rectangle (see Figure 4).

Run the application to see the skin
applied.

Figure 4. Run the application to see the skin applied.

Displaying content within a skin

In this section, you will use a Flex container control to display the Employee Portal application through the ApplicationContainerSkin skin.

  1. Return to the ApplicationContainerSkin.mxml file in Flash Builder.
  2. Below the closing Rect tag, create a Group container and assign the id property value to contentGroup:

    </s:Rect>
        <s:Group id="contentGroup">
        </s:Group>
  3. Save the file and run the application.

    You should see the Employee Portal application is now visible, but is not aligned properly (see Figure 5).

    Run the application to see the skin
applied.

    Figure 5. Run the application to see the skin applied.

  4. Return to Flash Builder.
  5. To the Group container, assign the left property value to 20, the right property value to 10, the top property value to 25 and the bottom property value to 10.

    <s:Group id="contentGroup"
        left="20" right="10" 
        top="25" bottom="10">
             
    </s:Group>
  6. Save the file and run the application.

You should see the Employee Portal application is now centered within the skin (see Figure 6).

Run the application to see the
EmployeePortal application is now centered in the skin.

Figure 6. Run the application to see the EmployeePortal application is now centered in the skin.

Skinning a Flex container

In this section, you will apply a skin to the EmployeePortal header image.

  1. From the Package Explorer view, open the TopContainerSkin.mxml file.

    Note that the TopContainerSkin.mxml file contains code that is the same as the ApplicationContainerSkin.mxml file.

  2. Open the EmployeePortal.mxml file.
  3. Locate the SkinnableContainer tag block.

    <s:SkinnableContainer width="933" height="81"
       contentBackgroundColor="0x0074aa">
     
        ...
            
    </s:SkinnableContainer>
  4. From the opening tag, remove the contentBackgroundColor property value.

    <s:SkinnableContainer width="933" height="81">
     
        ...
            
    </s:SkinnableContainer>
  5. To the SkinnableContainer tag, assign the skinClass property value to skins.TopContainerSkin:

    <s:SkinnableContainer width="933" height="81"
        skinClass="skins.TopContainerSkin">
     
        ...
            
    </s:SkinnableContainer>
  6. Save the file and run the application.

    You should see the header of the Employee Portal application has a blue background (see Figure 7).

    Apply a skin to the application header.

    Figure 7. Apply a skin to the application header.

  7. Return to the EmployeePortal.mxml file in Flash Builder.
  8. From between the SkinnableContainer tags, cut the layout property tags.
  9. Open the TopContainerSkin.mxml file.
  10. Locate the Group container.
  11. Between the Group container tags, paste the layout property code that was cut in step 8:

    <s:Group id="contentGroup"
        verticalCenter="0" 
        left="20">
              
        <s:layout>
           <s:HorizontalLayout/>
        </s:layout>
            
    </s:Group>
  12. Save the file and run the application.

You should see there has been no visual change committed to the application (see Figure 8).

Run the application to see there is no
change.

Figure 8. Run the application to see there is no change.

Applying a skin using CSS

In this section you will skin the application using a skin component and a CSS file.

  1. From the Package Explorer view, open the PanelSkin.mxml file.

    Note that the code is similar to the code within the ApplicationContainerSkin.mxml file you created earlier.

  2. From the Package Explorer view, open the EmployeePortal.css file.
  3. Locate the selector for Spark Panel containers.
  4. Within the selector, use the classReference() function to assign the skinClass property value to the skin.PanelSkin component.

    s|Panel
    {
        backgroundColor: #E8E8E8;
        skinClass:ClassReference("skins.PanelSkin");
    }
  5. Save the file and run the application.

You should see that the panels are skinned (see Figure 9).

Apply a skin to the Panel containers
within the application.

Figure 9. Apply a skin to the Panel containers within the application.

Using FXG shapes created in Illustrator CS4

In this section you will learn how to use a Flash XML Graphic (FXG) file to style components in Flash Builder.

  1. Return to Flash Builder.
  2. From the Package Explorer view, open the TopSkin.fxg file.

    The TopSkin.fxg file was created using Adobe Illustrator CS4. The file opened in Illustrator CS4 appears as shown in Figure 10. Note that the only rounded corner is the top right corner.

    View the TopSkin.fxg file opened in Illustrator
CS4.

    Figure 10. View the TopSkin.fxg file opened in Illustrator CS4.

  3. Locate the Path tag.
  4. From the Path tag, copy the data property and its assigned value.

    <Path winding="nonZero"  ai:knockout="0" 
        data="M0 0L0 81.2002 933.425 81.3457
    933.587 13.2305C933.587 6.60303 928.214 1.23047 921.587 1.23047L774.585 1.23047
    0 0Z" >
        <fill>
          <SolidColor color="#0684b7"/>
        </fill>
     
    </Path>
  5. Open the TopContainerSkin.mxml file.
  6. Within the file, comment out the Rect tags and properties and uncomment the Path tags:

    <!--<s:Rect radiusX="4" radiusY="4" height="100%" width="100%">
            <s:fill>
               <mx:SolidColor id="topContainerSkin" color="#0D86B8"/>
            </s:fill>
            
        </s:Rect>-->
        <s:Path winding="nonZero"> 
          <s:fill>
            <s:SolidColor color="0x0D86B8"/>
        </s:fill>
           
    </s:Path>
  7. Within the opening Path tag, paste the data property and value copied from the TopSkin.fxg file:

    <s:Path winding="nonZero" data="M0 0L0 81.2002 933.425 81.3457
    933.587 13.2305C933.587 6.60303 928.214 1.23047 921.587 1.23047L774.585 1.23047
    0 0Z">
          
        <s:fill>
            <s:SolidColor color="0x0D86B8"/>
        </s:fill>
           
    </s:Path>
  8. Save the file and run the application.

You should see that only the top right corner of the SkinnableContainer container skin is curved (see Figure 11).

Change the header skin to only have one
rounded corner.

Figure 11. Change the header skin to only have one rounded corner.

Creating a custom skin property

In this section, you will change the color of the title bar for each of the Panel containers within the Employee Portal application.

  1. Return to Flash Builder.
  2. Open the EmployeePortal.mxml file.
  3. Locate the HGroup container that nests the Panel containers.
  4. Between the HGroup tags, use comments to prevent the Panel container code from compiling.

    <s:HGroup gap="36">
       <!--<s:Panel width="287" height="472" title="Employee of the Month">
               <components:EmployeeOfTheMonth/>           
    
            </s:Panel>
     
            <s:Panel width="287" height="472" title="Cafeteria Special">
               <components:Cafeteria  width="100%"/>           
    
            </s:Panel>
            
            <s:Panel width="287" height="472" title="Monthly Events">
               <components:MonthlyEvents height="439" width="287"/>
            </s:Panel>-->
         
        </s:HGroup>
  5. In the Package Explorer, right-click the components package and select New > MXML Component (see Figure 12).

    Create a new MXML component.

    Figure 12. Create a new MXML component.

  6. Name the MXML component EmployeePortalPanel.
  7. Click the Browse button next to the Based on field.
  8. In the Based on dialog box, type Panel and select the Spark Panel container (see Figure 13).

    Base the new MXML component on the Spark
Panel container.

    Figure 13. Base the new MXML component on the Spark Panel container.

  9. Click OK.
  10. In the New MXML Component dialog box, type 287 for the Height value and 472 for the Width values (see Figure 14).

    Name the component EmployeePortalPanel,
base it on the Spark Panel container and delete the Width and Height.

    Figure 14. Name the component EmployeePortalPanel, base it on the Spark Panel container, and replace the Width and Heigh valuest.

  11. Click Finish.

    The EmployePortalPanel.mxml file will open in the Flash Builder editor.

  12. From the EmployeePortalPanel.mxml file, delete the Declarations tag block.
  13. Between the Panel container tags, create a Script block:

    <s:Panel xmlns:fx="http://ns.adobe.com/mxml/2009" 
       xmlns:s="library://ns.adobe.com/flex/spark" 
       xmlns:mx="library://ns.adobe.com/flex/halo">
        
        <fx:Script>
            <![CDATA[
             
            ]]>
        </fx:Script>
        
    </s:Panel>
  14. Within the Script block, declare a public variable named panelTitleColor data typed to the uint class:

    <fx:Script>
        <![CDATA[
     
            public var panelTitleColor:uint;
               
    
        ]]>
    </fx:Script>
  15. Save the file.
  16. Open the EmployeePortal.mxml file.
  17. Within the HGroup that contains the commented Panel container code, below the commented code, create an instance of the EmployeePortalPanel component.

    ... 
        </s:Panel>-->
            
        <components:EmployeePortalPanel>
     
        </components:EmployeePortalPanel>
         
    </s:HGroup>
  18. To the EmployeePortalPanel component instance, assign the title property value to Employee of the Month and use the code lookup tool to add the panelTitleColor property (see Figure 15).

    Use code lookup to add the
panelTitleColor property to the EmployeePortalPanel tag.

    Figure 15. Use code lookup to add the panelTitleColor property to the EmployeePortalPanel tag.

  19. Assign the panelTitleColor property value to #64BC48 (green):

    <components:EmployeePortalPanel title="Employee of the Month" 
        panelTitleColor="#64BC48">
               
    
    </components:EmployeePortalPanel>
  20. Within the EmployeePortalPanel component tags, add an instance of the EmployeeOfTheMonth component:

    <components:EmployeePortalPanel title="Employee of the Month" 
        panelTitleColor="#64BC48">
               
    
        <components:EmployeeOfTheMonth/>
               
    
    </components:EmployeePortalPanel>
  21. Save the file and run the application.

You should see only the Employee of the Month panel displayed and the panel's title color has not changed (see Figure 16).

Display the EmployeeOfTheMonth component using
the EmployeePortalPanel component.

Figure 16. Display the EmployeeOfTheMonth component using the EmployeePortalPanel component.

Passing a value to a custom skin property

In this section you will create a function to handle the passing of the panelTitleColor property value from the main application file to the custom component.

  1. Return to Flash Builder and open the PanelSkin.mxml file.
  2. Locate the nested fill property within the Path tag block.
  3. From the nested SolidColor tag, remove the color property value:

    <s:fill>
        <s:SolidColor/>
    </s:fill>
  4. To the SolidColor tag, assign the id property to headerSkinColor:

    <s:fill>
        <s:SolidColor id="headerSkinColor"/>
    </s:fill>
  5. Locate the MetaData tags.
  6. Within the HostComponent() function, change the value to reference the EmployeePortalPanel component:

    <fx:Metadata>
            
        [HostComponent("components.EmployeePortalPanel")]
            
    </fx:Metadata>
  7. Locate the Script comment and add a Script block below it:

    <!-- Script
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
        
    <fx:Script>
        <![CDATA[    
             
        ]]>
    </fx:Script>
    ...
  8. Within the Script block, create a private function named initTitleSkin that returns a void data type:

    <fx:Script>
        <![CDATA[    
               
    
            private function initTitleSkin():void
            {
    
            }
               
    
        ]]>
    </fx:Script>
  9. Within the initTitleSkin() function, assign the color property of the headerSkinColor SolidColor fill to the hostComponent.panelTitleColor property value:

    private function initTitleSkin():void
    {
        headerSkinColor.color = hostComponent.panelTitleColor;
    }
  10. To the opening SparkSkin tag, assign the creationComplete property value to call the initTitleSkin() function:

    <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" 
        creationComplete="initTitleSkin()">
  11. Save the file and run the application.

    You should see the Employee of the Month panel title skin is the color green (see Figure 17).

    Change the Employee of the Month Panel
container's header color to green.

    Figure 17. Change the Employee of the Month Panel container's header color to green.

  12. Return to the EmployeePortal.mxml file in Flash Builder.
  13. Within the HGroup container that nests the EmployeePortalPanel component, copy the component and paste two instances below the first:

    ...
        <components:EmployeePortalPanel title="Employee of the Month" 
           panelTitleColor="#64BC48">
               
        <components:EmployeeOfTheMonth/>
               
    
        </components:EmployeePortalPanel>
            
        <components:EmployeePortalPanel title="Employee of the Month" 
           panelTitleColor="#64BC48">
           <components:EmployeeOfTheMonth/>
             
        </components:EmployeePortalPanel>
             
        <components:EmployeePortalPanel title="Employee of the Month" 
           panelTitleColor="#64BC48">
             
            <components:EmployeeOfTheMonth/>
             
        </components:EmployeePortalPanel>
         
    </s:HGroup>
  14. To the second instance of the EmployeePortalPanel component, reassign the title property to Cafeteria Special, the panelTitleColor property value to #F05123 (orange) and change the nested component to the Cafeteria component.

    <components:EmployeePortalPanel title="Cafeteria Special" 
        panelTitleColor="#F05123">
               
    
        <components:Cafeteria/>
               
    
    </components:EmployeePortalPanel>
  15. To the third instance of the EmployeePortalPanel component, reassign the title property to Monthly Events, the panelTitleColor property value to #0D86B8 (blue) and change the nested component to the MonthlyEvents component.

    <components:EmployeePortalPanel title="Monthly Events"
    
        panelTitleColor="#0D86B8">
               
    
        <components:MonthlyEvents/>
               
    
    </components:EmployeePortalPanel>
  16. Save the file and run the application.

You should see the three panels have different colored headers (see Figure 18).

Pass the EmployeePortalPanel component
the header color from the main appication.

Figure 18. Pass the EmployeePortalPanel component the header color from the main application.

Test your knowledge

What is the HostComponent metadata tag used for within a skin?
The HostComponent metadata tag identifies the host component of a Spark skin class and allows you to access the public members of the host component’s instance from within the skin.
Why would you need to define the Group container with an id of contentGroup in the skin?
The Group container with an id of contentGroup in the skin displays the complete content of the skin.
How can you apply a skin using CSS?
Use the classReference() function to assign the skinClass property value to the component being skinned.

About the author

Trilemetry, Inc is a development and education organization that implements a human-centered design approach to the creation of software and content. Their Adobe portfolio includes the Adobe ColdFusion Getting Started Experience, the Adobe Flex Getting Started Experience, the Flex in a Week video series, the official Adobe instructor-led training course Flex 3: Extending and Styling Components and more. They also create and support many Web applications from interactive Flash sites and corporate web sites to mission-critical business applications.