Flex 4 Spark Skinning

In Flex 3 the way you styled your applications was through css, style properties, importing images, and finally using flash via swf files to style the look of your application. The problem with this situation was css and styles allowed for a limited styling and images and swf files would increase the size of the compiled application really quickly. In the end, we didn’t have enough options and enough options that could be highly optimized. As you could already guess, this has all changed with Flex 4 and the new Spark components.

Before I can say how Spark components are different, let me define a specific term halo components. Halo components are Flex 3 components, specifically components that have the look and feel of the component directly connected to the logic and methods of the component. Spark components are different, the look and feel have been pulled away from the logic and methods. This make it so that one component and another component can look COMPLETELY different while still maintaining the same base logic, properties, and methods.

In Flex 3 we could easily style multiple different buttons, such as:
[swfobj src="http://unitedmindset.com/jonbcampos/wp-content/flex_content/skin_post/button/UM3SkinTest.swf" alt="

Having a hard time viewing this example? Click here to view.

" width="500" height="400"]

Having a hard time viewing this example? Click here to view.

Due to each button containing the same style properties, there are only so many combinations of properties and therefore each button still looks and feels similar – similarly to how brothers and sisters look the same.

Now, with Flex 4 we can make custom Spark skins to continue making our buttons look even more foreign from each other.
[swfobj src="http://unitedmindset.com/jonbcampos/wp-content/flex_content/skin_post/button_fx4/UMSkinTest.swf" alt="

Having a hard time viewing this example? Click here to view.

" width="500" height="400"]

Having a hard time viewing this example? Click here to view.

The first button is just a plain button with no skinning, the other three are very different, all due to the skin that is added on them. And yes, I do know that the buttons look horrible – I wasn’t going to pretty.

Skins Basics
As you first get into Spark skinning your immediately going to think “this takes forever!” Once you get over that feeling you will realize that by skinning your spark components you have the ability to literally make anything component you want with ease.

To start your skinning, first determine if you are basing this skin off of a component, specifically a spark component. Yes? Then just like my examples, you need to set the host component meta tag, and the defined states in your component. The reason you set your states is so that your skin works just like every other flex 4 mxml components states array. No? Then I guess you better go make the component core that you are planning to make and then later start making your skin.

The Host Component
The host component meta tag states what component this skin defines, also giving you access to the styles and properities inherit to the specific component.

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

Skin States
The skin states act just like states within mxml components. You can see this states feature from a previous blog post of mine: Flash Builder Feature: States.

Your initial button skin should look similar to this:

<?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/halo"">

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

    <s:states>
        <mx:State name="
up"/>
        <mx:State name="
down"/>
        <mx:State name="
over"/>
        <mx:State name="
disabled"/>
    </s:states>

</s:SparkSkin>

From this point on the look of the component is up to you. Typically you will start with a shape, set it’s fill and stroke and draw out your component, for some examples view the source of the different skin examples I have provided for you. After your initial or base component state, feel free to keep playing with the different states of your spark skin. At this point your imagination (and time) is your only limitation to the look, feel, transitions, and interaction of your new spark component skin.

The Circle Button

<?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/halo"
    minHeight="80" minWidth="80">

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

    <s:states>
        <mx:State name="up"/>
        <mx:State name="down"/>
        <mx:State name="over"/>
        <mx:State name="disabled"/>
    </s:states>

    <s:Ellipse left="0" top="0" right="0" bottom="0">
        <s:fill>
            <mx:RadialGradient>
                <mx:GradientEntry color="0xFF0000" ratio=".33"/>
                <mx:GradientEntry color="0x000000" ratio=".9"/>
            </mx:RadialGradient>
        </s:fill>
    </s:Ellipse>
    <s:Ellipse left="0" top="0" right="0" bottom="0" includeIn="over">
        <s:fill>
            <mx:RadialGradient>
                <mx:GradientEntry color="0xFFFFFF" ratio="0"/>
                <mx:GradientEntry color="0xFF0000" ratio=".33"/>
                <mx:GradientEntry color="0x0000FF" ratio=".66"/>
            </mx:RadialGradient>
        </s:fill>
    </s:Ellipse>

    <s:Label id="labelDisplay" horizontalCenter="0" verticalCenter="0" textAlign="center"/>

</s:SparkSkin>

The Diamond Button

<?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/halo"
    minHeight="80"
    minWidth="80">

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

    <s:states>
        <mx:State name="up"/>
        <mx:State name="down"/>
        <mx:State name="over"/>
        <mx:State name="disabled"/>
    </s:states>

    <s:Rect rotation="45" y="0" x="50" minHeight="80" minWidth="80">
        <s:stroke>
            <mx:SolidColorStroke color="0x000000" weight="1"/>
        </s:stroke>
        <s:fill>
            <mx:LinearGradient>
                <mx:GradientEntry color="0x00FF00"/>
                <mx:GradientEntry color="0x000000" ratio="0.1"/>
                <mx:GradientEntry color="0x0000FF"/>
            </mx:LinearGradient>
        </s:fill>
    </s:Rect>
    <s:Rect rotation="45" y="0" x="50" minHeight="80" minWidth="80" includeIn="over">
        <s:stroke>
            <mx:SolidColorStroke color="0x000000" weight="1"/>
        </s:stroke>
        <s:fill>
            <mx:LinearGradient>
                <mx:GradientEntry color="0x00FF00"/>
                <mx:GradientEntry color="0x000000" ratio="0.9"/>
                <mx:GradientEntry color="0x0000FF"/>
            </mx:LinearGradient>
        </s:fill>
    </s:Rect>

    <s:Label id="labelDisplay" horizontalCenter="0" verticalCenter="0" color="0xFFFFFF"/>

</s:SparkSkin>

The Link Button

<?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/halo">

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

    <s:states>
        <mx:State name="up"/>
        <mx:State name="down"/>
        <mx:State name="over"/>
        <mx:State name="disabled"/>
    </s:states>

    <s:Rect left="0" right="0" top="0" bottom="0">

    </s:Rect>

    <s:Rect left="0" right="0" top="0" bottom="0" includeIn="over" radiusX="15" radiusY="15">
        <s:stroke>
            <mx:SolidColorStroke weight="2" color="0x0000FF"/>
        </s:stroke>
        <s:fill>
            <mx:SolidColor color="0x0000FF"/>
        </s:fill>
    </s:Rect>

    <s:Label id="labelDisplay" left="10" right="10" top="10" bottom="10" color.over="0xFFFFFF"/>

</s:SparkSkin>

The Triangle Button

<?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/halo"
    minWidth="40" minHeight="40">

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

    <s:states>
        <mx:State name="up"/>
        <mx:State name="down"/>
        <mx:State name="over"/>
        <mx:State name="disabled"/>
    </s:states>

    <s:Path data="H 100 L 50 75 L 0 0">
        <s:filters>
            <s:DropShadowFilter blurX="20" blurY="20" alpha="0.5" distance="11" angle="90"/>
        </s:filters>
        <s:stroke>
            <mx:LinearGradientStroke weight="1">
                <mx:GradientEntry color="0x0000FF" ratio=".25"/>
                <mx:GradientEntry color="0xFFFFFF"/>
            </mx:LinearGradientStroke>
        </s:stroke>
        <s:fill>
            <mx:LinearGradient rotation="90">
                <mx:GradientEntry color="0xFFFFFF"/>
                <mx:GradientEntry color="0x0000FF"/>
            </mx:LinearGradient>
        </s:fill>
    </s:Path>

    <s:Path data="H 100 L 50 75 L 0 0" includeIn="over">
        <s:stroke>
            <mx:LinearGradientStroke weight="1">
                <mx:GradientEntry color="0x0000FF" ratio=".25"/>
                <mx:GradientEntry color="0xFFFFFF"/>
            </mx:LinearGradientStroke>
        </s:stroke>
        <s:fill>
            <mx:LinearGradient rotation="90">
                <mx:GradientEntry color="0xFFFFFF"/>
                <mx:GradientEntry color="0x0000FF" ratio=".25"/>
            </mx:LinearGradient>
        </s:fill>
    </s:Path>

    <s:Label id="labelDisplay" horizontalCenter="0" verticalCenter="-10"/>

</s:SparkSkin>

Packaging Skins
Since skins are basically just mxml components, you can asdoc your skin like any other mxml component and also package the skin within your application or library project.

CSS with Skin Files
Finally, you can directly assign you spark component’s skin class as such..

    <s:Button label="Button" skinClass="com.unitedmindset.skins.button.LinkButtonSkin"/>

… or you can put the skin information into your css sheets as such…

s|Button.diamond
{
    skinClass: ClassReference("com.unitedmindset.skins.button.DiamondSkin");
}

… and reference your skin via the component’s styleName properties.

    <s:Button label="Button" styleName="diamond"/>

Update: I’ve created a future post on how to do this with Flash Catalyst.

Updated the blog text to reflect the Flex 4 Beta 2 release. The view source is still the old code, please be aware. Because of that I’ve removed the view source files. Will update them shortly.

I’ve created another post detailing some new skinning workflows for Flash Builder 4

I’ve created a newer post that goes over creating your own Spark Component and how to package your custom Spark Skin with your own custom Spark Component.

Update:
Alexander Ovsov made a translation of this post into Romanian. Feel free to see it here: http://webhostinggeeks.com/science/spark-skinning-ro

Comments (36)

ChrisAugust 5th, 2009 at 12:58 pm

I have been interested in learning how to skin both spark and halo components.

I’m still trying to understand the whole the actual elements themselves have to all be together towards the bottom of the page and the action script and other non visual tags have to be located towards the top.

Jonathan CamposAugust 5th, 2009 at 1:31 pm

Technically the actual elements and the script COULD switch, but it is seen as best practice to place them in that order. And, one thing to remember about mxml, is the lower the visual element is in the mxml document, the higher the index order. So with…

<s:Group id="a"/>
<s:Group id="b"/>

b is in front of a visually.

Bob TribitAugust 21st, 2009 at 10:42 am

A+++ Would go to again. Great presentation, guys.

Jonathan CamposAugust 21st, 2009 at 11:05 am

Glad you liked it!

[...] Flex 4 Spark Skinning Post [...]

RameshSeptember 9th, 2009 at 9:36 am

This is super. I am still at Flex 3 and will not be able to upgrade for a few more months and in my project, I need a triangle button. Any thoughts on how I can achieve that without excessive graphics rogramming? Thanks

Jonathan CamposSeptember 9th, 2009 at 9:49 am

You can, it just is a different process.

In Fx3 you have the ability to set the component’s skin with an image. Use the skin (skin, upSkin, downSkin, overSkin, disabledSkin, etc) property on your button and set whatever image you want… done! Use Flash SWF files for the most optimized results. In Fx4 you don’t even have to worry about Flash and you get the optimization.

RameshSeptember 9th, 2009 at 10:51 am

Hi Jonathan, unfortunately that does not work as the button is rectangular in shape, even if I have a triangle image skin on it.

May be my photo shop skill is bad, but I don’t know how to create a GIF or JPG Image that has only a triangle and no background color or matte. If I attach my triangle image skin on the button, the background color of the image shows up along with my colored triangle.

I hope I am explaining my problem to you well enough to be understood. Thanks, Ramesh

Jonathan CamposSeptember 9th, 2009 at 10:53 am

No, that makes sense. The problem is that you are using jpg and gifs. Try using a swf or png with a transparent background. That will give you your desired effect.

RameshSeptember 9th, 2009 at 11:22 am

Thank you. PNG worked great.

Nick WOctober 22nd, 2009 at 2:07 pm

Thank you for your clear explanation of how to properly skin spark buttons. It has to be the best I’ve found online. There is one thing I wanted to point out though.

Due to a change in how text will be represented in buttons, as I found out from here:

http://opensource.adobe.com/wiki/display/flexsdk/Spark+Text+Primitives+Decision

I believe your examples will need to replace:

with:

At least this is what I had to do in my skins when upgrading from Flash Builder Beta 1 to Beta 2.

Jonathan CamposOctober 22nd, 2009 at 2:15 pm

Thank you Nick, and you are right. I need to update the examples to reflect the newest SDKs.

IngoJanuary 15th, 2010 at 12:46 pm

Jonathan,
thanks for the post.
SimpleText throws an error on my build.
workaround: just use Label , with the id as discussed above.

Jonathan CamposFebruary 2nd, 2010 at 2:01 pm

Updated the examples to be up with the newest Fx4 build.

prasadFebruary 6th, 2010 at 12:18 am

thanks for the explanation. can i have some inputs on how to apply background attachment/background image to certain control.
regards.

Jonathan CamposFebruary 8th, 2010 at 9:05 am

Check out what dev girl did, it should explain background images well.

DaveFebruary 23rd, 2010 at 2:09 pm

Thanks for the simple breakdown. How would these look separated out to a css file? Do you leave the host component meta tag declaration in the mxml file, and simply define the style properties for the various states in the css? Also, whats the best way to match styles in an application that is being developed in Flex 3 and flash builder 4? My biggest hurdle as a non-programmer/designer, is trying to make the two look and act the same while being constrained to only halo components in one application and the changing nature of a beta development tool in the other. Do you have any resource suggestions for a novice in this situation?

Thanks in advance!

Jonathan CamposFebruary 25th, 2010 at 8:58 am

@dave What do you mean “how would these look separated out to a css file?”. My example shows how to include skins in css. The whole skin file would not go into a css file.

Yes, the host component would stay in the proper skin file.

The best ways to match styles of halo components in a Fx4 project would be to use the “halo” default theme. This simple theme will make your Fx4 spark components look like halo components… or use halo components :)

Let me know what other resource suggestions you are looking for and I’d be happy to point you in a direction, what is it you are trying to learn?

[...] few months ago I put together a blog entry on Spark Skinning. This entry was based off of Flash Builder Beta 1 and there have been many improvements to Flex 4 [...]

Flex 4 – BookMarks | Flex CertificationMarch 24th, 2010 at 2:13 am

[...] Flex 4 Spark Skinning Post [...]

Flex 4 in brief | Flex CertificationMarch 26th, 2010 at 2:24 am

[...] Flex 4 Spark Skinning Post [...]

Flex 4 Spark Skinning « Wookie DeveloperApril 16th, 2010 at 3:40 am

[...] Aquí encontrarás mayor información de Spark: http://unitedmindset.com/jonbcampos/2009/07/02/flex-4-spark-skinning/ [...]

[...] gives me an opportunity to throw some props to local Flex developer and guru, Jonathan Campos.  Take some time to review his Spark skinning tutorial.  I created a ‘minimal’ [...]

[...] of my posts on Spark Skinning… Flex 4 Spark Skinning Flash Catalyst – The Missing Visual Editor The New Spark Skinning [...]

[...] of my posts on Spark Skinning… Flex 4 Spark Skinning Flash Catalyst – The Missing Visual Editor The New Spark Skinning [...]

[...] in Flex 3. If you want more information on Spark Skinning check out some of my other posts: Flex 4 Spark Skinning New Spark Skinning Workflow Spark Skinning with Flash Catalyst var a2a_config = a2a_config || [...]

PhilipJuly 28th, 2010 at 10:07 am

Awesome ! Many thanks for that !

[...] View post: Flex 4 Spark Skinning | UnitedMindset [...]

[...] This post was mentioned on Twitter by Dennis Plucinik, junichi_y. junichi_y said: Flex 4 Spark Skinning | Jonathan Campos' Blog: http://bit.ly/esJOHP [...]

manojApril 25th, 2011 at 3:42 am

Can i take jpg image or vector graphics in button background in flex 4.

Thanks

jonbcamposApril 25th, 2011 at 9:04 am

@manoj Yes you can. Just use a BitmapAsset and you’ll be good to go.

GautamOctober 8th, 2011 at 11:14 pm

Nice example. Thanks

[...] and skin classes I’m not going to go into skinning in this post, but if you are curious, here is a good blog post, which shows how to create skins for Flex 4 [...]

RajaFebruary 15th, 2012 at 10:38 am

Hi, i have Login form item text input for mobile application. the text input data is erasing on each orientation change…how can we maintain the data…….can any one please help me….

jonbcamposFebruary 21st, 2012 at 9:19 am

@raja you can always listen for orientationChange events and reset the data as necessary.

Tahir AlviDecember 19th, 2012 at 2:11 am

Nice article cover all aspects of spark skinning.

Thank You

Leave a comment

Your comment