Home >
My general idea last week was that I was going to whip together a tutorial similar to last week's post, where I used Flex Builder's design view to build something like this:
I will admit for the record that what I'm showing above is something I haven't done before, but I was using this column as an excuse to play around with. So I had no idea when I started that Design View doesn't lend itself very well to the process. What that means is that there wasn't much point in taking screen captures showing you the process. What I have done is enable View Source on the above movie so you can see what the final code looks like. I also left some of my failed attempts in there, so you can see what didn't work (actually ButtonSkin_3 also would have worked, but wasn't as clean as ButtonSkin_4).
Instead of a full-blown tutorial, I thought I'd share a few concepts about how I approached the problem and what I learned in the process.
Before I start to talk about that, though, I'd like to back up a moment and talk about why I've been intrigued with the idea of stateful skins. Normally, when we skin a component in Flex, we do one of three things:
- We just use graphics that get switched out from one to another as the button is rolled over, pressed, selected, or what have you. These don't really do anything, just switch.
- We go out to Flash and design our skin there. Once we're back in Flex, the skin is then a "black box" that can't be edited in Flex—it can only be changed in Flash.
- We sharpen up our coding pencil and write a programmatic skin. This has a high barrier to entry, but it makes you look like a genius if you can pull it off. And more of a genius if you can figure out in 6 months what you were on when you did it.
Stateful skins, on the other hand, are really simple to understand for people of any skill level. They offer more options for what you can do between states, and there's a lot you can do without adding ActionScript code.
However, even though they are simple to understand, they are not well documented and there are a few quirks both of stateful skins and of how some of the components work that meant that this whole odyssey was "easier said than done." So maybe by joining me on my journey you can benefit from the simplicity and power without hitting all of the headaches.
The first thing I did was to hit the documentation for Button. This told me what States I needed to build for.

I chose to only build for the first three, because as you can see in the example button above, there wasn't anything to disable the button or select it.
I also noticed that there were two key words preceding the list of states. On the assumption that the docs would be relatively standardized, I switched the Help to my Language Reference Scope and searched on those words. This yeilded what I suspect is a fairly complete list of components that support stateful skins.

I started out by trying to extend Image class. I found out a few things about Image class that you should know if you're going to use it for or in a Stateful Skin.
- If you choose a source graphic for it in Design Mode, that graphic will be linked, not embedded. I could not find a way to get the "Browse" button to bring that path into an Embed statement.
- The scale9Grid property on Image control seems to have some serious problems that mean that seem to mean that you can't use it in the context of a skin. I found that in most cases if the property was applied before the content had loaded, the grid wasn't used. If it was set with the correct parameters after the content had loaded, it generated an error because it apparently thought the rectangle was larger than the Bitmap. One time I managed to run the code and it worked, but then a couple of hours later the same code caused errors.
- As a result of (2), I concluded that the only workable way was to use embedded graphics and switch out the source to one of the various png Classes, each of which had its own scale9 information in the Embed statement..
- The scale9 information only applies in both directions if you set the scaleContent property on the Image to true and the maintainAspectRatio property to false. These seem to be set the opposite way by default.
Another variation I tried at several stages was to use a Canvas, both with and without an Image control. One reason I decided to use Canvas was because it had a "color" style property I naïvely assumed that the Button would somehow pick up a changed "color" off of the skin file and apply it to its own text. Wrong again. To get a downColor property in Flex 3, I think I'm just going to have to extend Button, though I'd be really surprised if it weren't in Flex 4. Another idiosyncracy of Canvas as a button skin is that if you give it a 9-sliced embedded graphic as a background, it doesn't seem to scale properly to fill the space. Instead, the graphic stays at its original size in the center of the button.
Finally, I kind of thought I might be able to do some interesting things with the size of my image by using a Zoom transition to zoom it up on the Over state and then back down when the cursor rolled out. What happened in reality is when I tried to zoom it up it just moved up and to the left, and when I tried to zoom it down, it moved down and to the right. I think that changing the size of the component itself while the Button is trying tto use it as a skin just confuses Button, so it can't lay itself out properly. The strange movement is its way of coping.
So there you have it...three days of aggravation boiled down into a bitesized morsel.




Facebook Application Development
Errr... no source view enabled.
Just so you know, the whole process of states & skins is changed up and made much much easier to use/understand in Flex 4
I'm just responding to Sine's comment so that people who might be discouraged by it will not be put off by what he/she said. The View Source option works just fine.
Really nice. I really like. Thanks for sharing.
Just checked... view source opening a page not found!
Oh, it looks like the view source is local to the html and not the swf. I could have sworn this was working before. Try this link:
http://www.magnoliamultimedia.com/InsideRIA/stateful.htm
Still not working the source view.
Sorry...Fixed now :-)