« Flash Lite 1.1 Inline Text | Main | Simple Flex 2 Messaging Example »

February 03, 2006

Programmatic Skinning with Flex 2

Inspired by my friend Waldo Smeet's blog entry on using 9-slice and Flash 8 to skin Flex 2 components, it occurred to me that not everybody wants to use the Flash authoring tool. In fact, Flex was created for those enterprise developers who appreciated the power of a ubiquitous runtime, but who weren't particularly interested in mastering timelines, keyframes, symbols and the myriad of other designer-oriented aspects of the authoring tool. Lucky for us, Flex 2 also includes a very impressive programmatic skinning feature. That's right, if you can draw it using the Drawing API (which I might remind you has become incredibly powerful with Flash 8), then you can use it as a skin.

The first thing you need to do when creating a programmatic skin is to choose a base class from which to extend. There are three to choose from (ProgrammaticSkin, Border and RectBorder) based on your particular requirements. The next step is to override the updateDisplayList() method. It's here where you'll draw whatever it is that you want your skin to look like. Of course not all skins always carry the same appearance, sometimes the skin changes based on a particular state. By checking on the name of the skin that is being requested (through an inherited property of the skin classes), you can change what it is your drawing at runtime.

It is also possible to look up the parent component to further customize your skin. Using this ability, you can create one skin class, or a parent skin class that leverage others, to encompass all the different states of all the different controls you are using in your entire application. In the case of the Service Manager skin, I wanted to have the skewed rectangular shape blend in with the rest of the application. This meant determining the if the header being drawn was the first, last, or somewhere in-between. Armed with this information, we can account for headers that reach into the main user interface.

You might think that there is something tricky that comes next. Certainly it couldn't be as easy as a little AS3 subclass? Indeed, if you're using Flex Builder, that's all there is to it. The last step is simply to assign the class to the skin style properties. In classic Flex fashion, this is typically done in a CSS file. Where you might generally use "font-size: 10;" as a style, here there's a little twist on the syntax. You must tell the style what class you are using through a ClassReference entry which takes the form of "upSkin: ClassReference( "ServiceManagerSkins" );". As you look through the API reference you'll see many "xxxSkin" style properties - those are all the skins you can use (programmatically or otherwise).

As somebody who really likes to customize the look of his applications, the new skinning features in Flex 2 really opens up the possibilities. It should go without saying that there's a substantial number of new style properties alone, so skinning may often be overkill in many cases. And all the other features? What's not to love about the entire line-up? The code for my skinning example is attached, and as usual here's a screenshot of the results.

Service Manager Accordion

Posted by khoyt at February 3, 2006 08:24 PM

Comments

Nice article Kevin. It's really good to see both sides of the story and see all potential designer - developer integration scenarios.

I was particularly interested in seeing the differences with Flex 1.5 programmatic skins. I created exactly this programmatic Trio skin last year in Flex 1.5 but hadn't studied the new Flex 2 architecture.

I'm really pleased to see that's been improved a lot and requires less 'ugly' code to get something nice to render on the screen. No more symbolName, symbolOwner, UIObjectExtensions and _global.skinRegistry uglyness ;-)

Posted by: Waldo Smeets at February 4, 2006 02:46 AM

Thanks for pointing this out. Very elegant!

Posted by: dominick accattato at February 6, 2006 08:57 AM

hi,Mr Hoyt
Could I ask you a question?

I want to implement these function:
when main.mxml initialize,it create children(mainpanel,childpanel),if I click the mainpanel's
Button ,it produce a String,then the String are sent to childpanel,how can I implement?

Thank you very much.

main.mxml


HistoryPanel:

NewPanel

Posted by: orant at February 13, 2006 06:42 AM

Could I ask you a question?

I want to implement these function:
when main.mxml initialize,it create children(mainpanel,childpanel),if I click the mainpanel's
Button ,it produce a String,then the String are sent to childpanel,how can I implement?

Thank you very much.

main.mxml


HistoryPanel:

NewPanel

Posted by: orant at February 13, 2006 06:43 AM

This doesnt seem to compile in 2.0.1. Changed the namespace to Adobe and the .as class was trying to import flash.util.* I assume you mean utils.* but it just comes up blank now, if i comment out <mx:Style.. tho the component obviously appears.

MaTT

Posted by: matt at January 31, 2007 03:04 AM

Hey Matt,

Thanks for the tip! I've updated the source to work under 2.0.1.

Thanks again,
Kevin

Posted by: Kevin Hoyt at February 1, 2007 07:33 AM

Post a comment




Remember Me?