In this article I will create a custom Spark Panel component that will look something like this:
You can find the working example lower on this page.
There are five steps that you must take to create a new Flex 4 Skin (for any Spark component):
- Create a new
MXML
component that extends the SparkSkin class - Define the states of the Skin. The default states for most of the components are
normal
anddisabled
- Define the
HostComponent
betweenMetadata
tags - Specify all the graphical elements that are used by the custom Skin
- Define the skin parts for the skin
So the first thing that I did was to create a custom MXML component for the Spark Panel skin. I created this component in the skins
folder and I named the custom skin PanelSkin
.
The next step was to define the states of the skin. To see what states are available for any Spark component you should check out the Adobe ActionScript 3.0 Reference for the Adobe Flash Platform online documentation.
For the Spark Panel custom skin I used four states:
<s:states> <s:State name="normal" /> <s:State name="disabled" /> <s:State name="normalWithControlBar" /> <s:State name="disabledWithControlBar" /> </s:states> |
The normal
and disabled
states are the default states when the Panel does not have a Control Bar. The normalWithControlBar
and disabledWithControlBar
states are used when the Panel is defined with a Control Bar.
Next we need to specify the HostComponent
between Metadata
tags. The HostComponent
will be the path to the Spark component that will be skinned. In this case: spark.components.Panel
:
<fx:Metadata> [HostComponent("spark.components.Panel")] </fx:Metadata> |
Next I specified all the graphical elements of the skin:
<s:BorderContainer color="0xAAAAAA" cornerRadius="7" width="100%" height="100%"> <s:Rect width="100%" height="45" topLeftRadiusX="7" topLeftRadiusY="7" topRightRadiusX="7" topRightRadiusY="7" top="0"> <s:fill> <s:LinearGradient rotation="90"> <s:entries> <s:GradientEntry color="#bf0000" /> <s:GradientEntry color="#ff0011" /> </s:entries> </s:LinearGradient> </s:fill> </s:Rect> <s:Rect bottomLeftRadiusX="7" bottomRightRadiusX="7" y="45" width="100%" height="100%"> <s:fill> <s:LinearGradient rotation="90"> <s:entries> <s:GradientEntry color="#f8f8f8" /> <s:GradientEntry color="#CCCCCC" /> </s:entries> </s:LinearGradient> </s:fill> </s:Rect> <s:Rect width="100%" height="40" excludeFrom="normal, disabled" bottomLeftRadiusX="7" bottomLeftRadiusY="7" bottomRightRadiusX="7" bottomRightRadiusY="7" bottom="0"> <s:fill> <s:LinearGradient rotation="90"> <s:entries> <s:GradientEntry color="#3f3f3f" /> <s:GradientEntry color="#a5a5a5" /> </s:entries> </s:LinearGradient> </s:fill> </s:Rect> </s:BorderContainer> |
At a glance this looks like a lot of code, but it is actually pretty straight forward. I declared a BorderContainer
and inside this another three Rect
blocks for the Panel header, Panel body and Panel Control Bar.
Inside every Rect
block I have LinearGradient
with different colors for every Rect
. In the last Rect
I added this code excludeFrom="normal, disabled"
which will exclude this Control Bar from the Skin when the panel is declared without the Control Bar.
The last step is to define the skin parts
. The Spark Panel has three skin parts
: contentGroup
for the Panel body, controlBarGroup
for the Panel Control Group and titleDisplay
for the Panel Header:
<s:Label id="titleDisplay" paddingLeft="15" paddingRight="15" paddingTop="15" color="white" fontSize="18" fontWeight="bold" fontStyle="italic"/> <s:Group id="contentGroup"> <s:layout> <s:VerticalLayout paddingTop="55" paddingBottom="10" paddingLeft="15" paddingRight="15" paddingBottom.disabledWithControlBar="55" paddingTop.disabledWithControlBar="55" paddingBottom.normalWithControlBar="55" paddingTop.normalWithControlBar="55"/> </s:layout> </s:Group> <s:Group id="controlBarGroup" bottom="10"> <s:layout> <s:HorizontalLayout paddingLeft="5" paddingRight="5"/> </s:layout> </s:Group> |
Ok, that’s all as far as the Panel Custom Skin is concerned. Now I will focus on the applying the Custom Skin to a few Panel instance in the application. To apply a Custom Skin to a Spark component you will use skinClass
property like this:
<s:Panel id="myPanel1" skinClass="skins.PanelSkin" title="My first panel title"> |
Here is the resulting application:
View Source is enabled in the above example. To view the source files right click on the swf and choose “View Source” from the context menu.
Here is the complete source code for the main application:
<?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/mx" viewSourceURL="srcview/index.html"> <s:layout> <s:HorizontalLayout paddingTop="5" horizontalAlign="center" verticalAlign="middle"/> </s:layout> <s:Panel id="myPanel1" skinClass="skins.PanelSkin" title="My first panel title"> <mx:Text text="Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. " width="200" /> <s:controlBarContent> <s:Button label="First Button"/> <s:Button label="Second Button"/> </s:controlBarContent> </s:Panel> <s:Panel id="myPanel2" skinClass="skins.PanelSkin" title="My second panel title"> <mx:Text text="Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. " width="200" /> </s:Panel> </s:Application> |
And here is the complete source code for the Custom Skin Class:
<?xml version="1.0" encoding="utf-8"?> <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/mx" alpha.disabled="0.5" blendMode="normal"> <s:states> <s:State name="normal" /> <s:State name="disabled" /> <s:State name="normalWithControlBar" /> <s:State name="disabledWithControlBar" /> </s:states> <fx:Metadata> [HostComponent("spark.components.Panel")] </fx:Metadata> <s:BorderContainer color="0xAAAAAA" cornerRadius="7" width="100%" height="100%"> <s:Rect width="100%" height="45" topLeftRadiusX="7" topLeftRadiusY="7" topRightRadiusX="7" topRightRadiusY="7" top="0"> <s:fill> <s:LinearGradient rotation="90"> <s:entries> <s:GradientEntry color="#bf0000" /> <s:GradientEntry color="#ff0011" /> </s:entries> </s:LinearGradient> </s:fill> </s:Rect> <s:Rect bottomLeftRadiusX="7" bottomRightRadiusX="7" y="45" width="100%" height="100%"> <s:fill> <s:LinearGradient rotation="90"> <s:entries> <s:GradientEntry color="#f8f8f8" /> <s:GradientEntry color="#CCCCCC" /> </s:entries> </s:LinearGradient> </s:fill> </s:Rect> <s:Rect width="100%" height="40" excludeFrom="normal, disabled" bottomLeftRadiusX="7" bottomLeftRadiusY="7" bottomRightRadiusX="7" bottomRightRadiusY="7" bottom="0"> <s:fill> <s:LinearGradient rotation="90"> <s:entries> <s:GradientEntry color="#3f3f3f" /> <s:GradientEntry color="#a5a5a5" /> </s:entries> </s:LinearGradient> </s:fill> </s:Rect> </s:BorderContainer> <s:Label id="titleDisplay" paddingLeft="15" paddingRight="15" paddingTop="15" color="white" fontSize="18" fontWeight="bold" fontStyle="italic"/> <s:Group id="contentGroup"> <s:layout> <s:VerticalLayout paddingTop="55" paddingBottom="10" paddingLeft="15" paddingRight="15" paddingBottom.disabledWithControlBar="55" paddingTop.disabledWithControlBar="55" paddingBottom.normalWithControlBar="55" paddingTop.normalWithControlBar="55"/> </s:layout> </s:Group> <s:Group id="controlBarGroup" bottom="10"> <s:layout> <s:HorizontalLayout paddingLeft="5" paddingRight="5"/> </s:layout> </s:Group> </s:SparkSkin> |