The new component / skin separation in Flex 4 (the Spark Architecture) is pretty nifty. But if you want to add a configurable style to a skin then that style must be defined on the component. For instance if you want to add a backgroundColor style to a Button skin then you need to first create a new Button component with the style on it:
package { import spark.components.Button; [Style(name="backgroundColor", type="uint", format="Color")] public class SButton extends Button { } }
Then create a new Button skin that uses the style:
<?xml version="1.0"?> <s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark"> <fx:Script> import mx.utils.ColorUtil; </fx:Script> <s:states> <s:State name="up"/> <s:State name="over"/> <s:State name="down"/> </s:states> <s:Rect width="100%" height="100%"> <s:fill> <s:SolidColor color="{getStyle('backgroundColor')}" color.over="{ColorUtil.adjustBrightness2(getStyle('backgroundColor'), 64)}" color.down="{ColorUtil.adjustBrightness2(getStyle('backgroundColor'), -32)}" /> </s:fill> </s:Rect> <s:Label id="labelDisplay" paddingBottom="3" paddingLeft="3" paddingRight="3" paddingTop="6"/> </s:SparkSkin>
Then you can use the new Button and skin:
<SButton label="backgroundColor = #ff0000" backgroundColor="#ff0000" skinClass="SButtonSkin"/> <SButton label="backgroundColor = #0000ff" backgroundColor="#0000ff" skinClass="SButtonSkin"/>
The reason that we had to create a new base class just to hold the style is because there would be no other way to set the style in MXML. We could have set the style via CSS or setStyle. Button does not have a style named “backgroundColor” so if we hadn’t created SButton and tried to just set a backgroundColor property on a Button instance via MXML, the compiler would have thrown an error.
So I (with the help of Ryan Frishberg and Mike Labriola) came up with a nifty little way to set styles on skins without having to create new base classes to hold the styles. The idea is that styles should be defined on the skins and you can use a property on the base components to set those styles via MXML. To make it happen I had to Monkey Patch a property named “style” onto UIComponent. In the setter for that style I just parse a string of HTML-ish styles and call setStyle. The cool thing is that I’m calling setStyle on the component but since skins inherit the styles of their host component the skin gets the styles. This also means that the styles don’t really need to be defined on the skins. Just used in the skins. Using the example above to set the backgroundColor on the Button I could just do:
<s:Button label="backgroundColor = #ff0000" style="backgroundColor: #ff0000" skinClass="SButtonSkin"/>I didn’t need a new Button class just to set the backgroundColor style. Here is a more complex example with more styles on the skin:
All of those buttons are using the same skin and the base Spark Button! The code for this example is on github. So check it out, fork it, and have fun. Let me know if you have any questions.


18 Comments
While trying to run it from git, got the below error
ReferenceError: Error #1056: Cannot create property style on spark.components.Button
You need to turn off the Framework RSLs in order for Monkey Patching to work. Let me know if that works.
This is great but it would be even better if the SDK supported this rather than having to Monkey Patch it. These real world requirements seem to have gotten lost in the engineering of the new Spark components. The idea of having to create custom skins and button classes just to set the background color of a button is kind of ridiculous. In my opinion, the components should be able to accept dynamic style attributes just for this reason. So you could do something like:
Sorry my code snippet got lost… the idea is to be able to specify an attribute like style:backgroundColor=”#ff0000″ and have it turn into the same as setStyle(“backgroundColor”, 0xff0000);
I’d love some official MXML syntax that would do this. Can you file a feature request and post it here?
I’m probably missing something huge here, but why not just add the styles to the skin and use CSS to style to skin instead of the component?
You can do that. But not everyone wants to use CSS all of the time.
Here is the link to the feature request: https://bugs.adobe.com/jira/browse/SDK-27186
maybe i am missing something more here, but i find it absolutely wrong having to duplicate tons of code just to change a background alpha value on a skin. If you want to change the skin background alpha, you need to create a new skin, duplicating ALL the original skin code and change it. This is unmaintainable. Just imagine that the original skins get updated or changed. You need to go skin by skin to update the base changes. This will lead to tons of duplicated code. Just what modern languages and OOP try to avoid. Maybe i am wrong???
Is it possible to extend the skin and modify only the alpha parameter so when the base skin changes, i do not need to also change the copy??
i hope i’m wrong, but from a developer point of view, this is a disaster.
It is not possible to extend MXML skins. Thus the reason that I created this project to show how skins can be reused by passing in style parameters.
Ok, but this does not solve the real problem with code reuse: At the moment we are copying one skin to create another one we are duplicating code that may change somewhere in the future, leading to big redundancy problems. If to use an existing skin we must duplicate it’s code, there’s a big problem here for those of us who want to reuse the maximum code possible (and i think all good developers think allways about it).
maybe i am wrong again, but seems that adobe is focusing more on “i don’t know f*** about developing” designers than in real developrers… so sad
Totally agree that not being able to extend skins and MXML based classes is sad. I’m not sure if there is a “feature request” for this in the Flex bug database yet. If not, file one so I can vote on it.
hope we see it on the future!
Hey James!
I tried this out on s:Application, wanting to get a transparent background for the application container. I simply created an .as class SApplication:
package components
{
import spark.components.Application;
[Style(name="backgroundAlpha",type="Number",default="0")]
public class SApplication extends Application
{
public function SApplication()
{
super();
}
}
}
I instantiated the new app class as such:
I created a new version of the spark ApplicationSkin and modified the override:
override protected function updateDisplayList(unscaledWidth:Number,
unscaledHeight:Number) : void
{
bgRectFill.color = getStyle('backgroundColor');
bgRectFill.alpha = getStyle('backgroundAlpha');
super.updateDisplayList(unscaledWidth, unscaledHeight);
}
as well as the SolidColor fill:
I also added the transparent wmode to swfObject embed to make sure my html bg was transparent:
var flashvars = {};
var params = {
params:wmode = "transparent"
};
var attributes = {};
var so = new SWFObject("src/drcFlex.swf", "drcFlex", "900", "250", "10", null, params, null);
so.write("flowNav");
And alas… I’ve got nothing – any ideas, see anything above that is incorrect, or different way to approach this????
Hope my code tags work :-)
BTW – was great to meet you last spring at FlashCamp Chicago!
Doug
follow me @dougrdotnet
missing code:
New app class:
SolidColor Fill:
Doug
I’ve never tried to make a Flex 4 app transparent. But check out this example:
http://kbala.com/how-to-create-transparent-application-background-spark-sdk/
Let me know if that works.
BTW: Wrap code with <pre> blocks.
Sweet!! I’ll write it up today and post back. Why I didn’t find that in my research, I have no idea.
Ya, sorry about that – feel free to kill that waste of space 2nd post :D
Should have known, My blog handles mxml the same way….And….I’m obviously too lazy to escape!!
Thanks!
James,
Ya K BalaSubramanian’s post was a better solution than my own – simpler. As it turns out my problem was actually in my configuration of SWFObject. After triple checking my js, I went over to http://www.bobbyvandersluis.com/swfobject/generator/index.html and used the SWFObject 2 HTML and JavaScript generator v1.2 – I was missing an the expressInstallSwfurl argument between version and flashvars arguments – swfobject.embedSWF(swfUrl, id, width, height, version, expressInstallSwfurl, flashvars, params, attributes, callbackFn).
So, there you go – simple to add a transparent background on s:Application – just gotta pay attention to details :-)
Thanks for the link!
HTH someone else too!
Doug