In Flex 3 you can use runtime CSS. Thus far in the chapter, when we’ve talked about CSS we’ve talked exclusively about CSS that gets compiled into the Flex application. Now we’ll look at how you can load and apply CSS at runtime, effectively restyling an application at runtime.
Because Flex styles often required embedded resources such as skin
assets, classes, and fonts, Flex runtime CSS must be precompiled into
.swf files. When using Flex 3, you
can use the mxmlc
compiler to compile a
.css file into an .swf that includes all assets embedded by the
.css file. To compile the .css file, simply pass the path to the file as
the one compiler argument, as in the following example:
mxmlc styles.css
The preceding example will compile styles.css into a file called styles.swf. You can then load styles.swf into your Flex applications at runtime without having to include the .css or any of the embedded assets in the main Flex application. That means you can update the styles for an application without having to recompile and redeploy the application itself. All you have to do is update the styles file. Furthermore, you can have many styles files that the user can choose from at runtime.
To load CSS at runtime, you use the StyleManager.loadStyleDeclarations()
method.
The loadStyleDeclarations()
method requires at least
one parameter—the path to the .swf
file containing the CSS:
StyleManager.loadStyleDeclarations("styles.swf");
If you’re loading only one stylesheet, as soon as you’ve loaded the
styles you’ll want to apply them. By default, loadStyleDeclarations()
behaves in this way.
However, if you are loading several stylesheets (runtime stylesheets have
the same cumulative potential as compile-time stylesheets), you likely
don’t want to apply the styles until after you’ve loaded the last
stylesheet. This is because applying styles is a relatively expensive
operation, and it is best to defer applying the styles until they have all
loaded. You can achieve this by specifying false
for the second parameter of all but the
last loadStyleDeclarations()
method call.
Then specify a value of true
(or do not
specify a value because the default is true) for the last loadStyleDeclarations()
method call.
StyleManager.loadStyleDeclarations("stylesA.swf", false); StyleManager.loadStyleDeclarations("stylesB.swf", false); StyleManager.loadStyleDeclarations("stylesC.swf", false); StyleManager.loadStyleDeclarations("stylesD.swf", true);
The loadStyleDeclarations()
method allows you to load stylesheets from the same domain as the Flex
application or from different domains. However, if you load the stylesheet
.swf file from a different domain,
you’ll need to specify true
for the
third (optional) parameter for loadStyleDeclarations()
:
StyleManager.loadStyleDeclarations("http://www.differentdomain.com/styles.swf", true, true);
Because styles are applied cumulatively, you need a mechanism for
clearing loaded CSS. You can achieve that using the StyleManager.unloadStyleDeclarations()
method.
The unloadStyleDeclarations()
method
requires that you specify the path to the .swf file that was originally loaded, and you
can optionally specify whether to immediately unload the styles or wait
until you’ve unloaded other styles:
StyleManager.unloadStyleDeclarations("styles.swf");
To best understand runtime CSS, here’s a simple exercise.
Create a file called a.css with the CSS in Example 8-33.
From a command prompt, compile a.css to a.swf using the following command (make
sure you’ve added mxmlc
to your
path):
mxmlc a.css
Create a file called b.css with the CSS in Example 8-34.
Example 8-34. b.css
@font-face { src: url("GOTHIC.ttf"); fontFamily: gothicCentury; } @font-face { src: url("GOTHICB.ttf"); fontFamily: gothicCentury; fontWeight: bold; } global { fontFamily: gothicCentury; } Application { themeColor: green; } Button { cornerRadius: 25; } ToolTip { borderSkin: ClassReference("com.oreilly.programmingflex.styles.ToolTipSkin"); }
You must ensure that com.oreilly.programmingflex.styles.ToolTipSkin
is available in the source path for the project. You created this
class earlier in the chapter.
From a command prompt, compile b.css to b.swf using the following command:
mxmlc b.css
Create a new document called RuntimeCSS.mxml with the code in Example 8-35.
Example 8-35. RuntimeCSS.mxml
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" initialize="initializeHandler(event)"> <mx:Script> <![CDATA[ private var _currentStyle:String; private function initializeHandler(event:Event):void { StyleManager.loadStyleDeclarations("a.swf"); _currentStyle = "a.swf"; } private function clickHandler(event:Event):void { StyleManager.unloadStyleDeclarations(_currentStyle); StyleManager.loadStyleDeclarations(stylesOptions.value.toString()); _currentStyle = stylesOptions.value as String; } ]]> </mx:Script> <mx:ComboBox id="stylesOptions" toolTip="Select a Style Sheet"> <mx:dataProvider> <mx:ArrayCollection> <mx:String>a.swf</mx:String> <mx:String>b.swf</mx:String> </mx:ArrayCollection> </mx:dataProvider> </mx:ComboBox> <mx:Button label="Change Style" click="clickHandler(event)" /> </mx:Application>
Compile and run RuntimeCSS.mxml.
When you run this test, you’ll be able to switch between two runtime
stylesheets and see the effects. Notice the difference if you comment the
unloadStyleDeclarations()
line.