Styles are useful for defining the look and feel of your applications, including letting users set component skins. You can use them to change the appearance of a single component, or apply them across all components, including custom components.
You can modify the appearance of Flex components through style properties. These properties can define the size of a font used in a control, or the background color used in the Tree control. In Flex, some styles are inherited from parent containers to their children, and across style types and classes. This means that you can define a style once, and then have that style apply to all controls of a single type or to a set of controls. Also, you can override individual properties for each control at a local, document, or global level, giving you great flexibility in controlling the appearance of your applications.
For more information, see Styles and themes.
When you implement a style property in an ActionScript component, that property is automatically inherited by any subclasses of your class, just as methods and properties are inherited. This type of inheritance is called object-oriented inheritance.
Some style properties also support Cascading Style Sheet (CSS) inheritance. CSS inheritance means that if you set the value of a style property on a parent container, a child of that container inherits the value of the property when your application runs. For example, if you define the fontFamily style as Times for a Panel container, all children of that container use Times for fontFamily, unless they override that property.
In general, color and text styles support CSS inheritance, regardless of whether they are set by using CSS or style properties. All other styles do not support CSS inheritance, unless otherwise noted.
If you set a style on a parent that does not support CSS inheritance, such as textDecoration, only the parent container uses that value, and not its children. There is an exception to the rules of CSS inheritance. If you use the global type selector in a CSS style definition, Flex applies those style properties to all controls, regardless of whether the properties are inheritable.
For more information about style inheritance, see About style inheritance.
Flex provide several ways of setting component styles: using MXML tag attributes, calling the setStyle() method, and CSS.
Component users can use MXML tag attributes to set a style property on a component. For example, the following code creates a TextArea control, and then sets the backgroundColor style of the component to blue (0x0000FF):
<mx:TextArea id="myTA" backgroundColor="0x0000FF"/>
Component users can use the setStyle() method to set a style property on a component. For example, the following code creates a TextArea control, and then sets the fontWeight style of the component to bold:
var myTA:TextArea=new TextArea();
myTA.setStyle('fontWeight', 'bold');
<?xml version="1.0" encoding="utf-8"?>
<!-- createcomps_styles/CCStyles.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:MyComp="myComponents.*" >
<fx:Style>
@namespace s "library://ns.adobe.com/flex/spark";
s|TextArea {fontWeight: "bold"}
</fx:Style>
<s:TextArea/>
</s:Application>
You can also import an external CSS file, as the following example shows:
<fx:Style source="myStyle.css"/>
When a user sets a style on a component, Flex calls the component's styleChanged() method, passing to it the name of the style being set. When you create a custom component, you can override the UIComponent.styleChanged() method to check the style name passed to it, and handle the change accordingly, as the following example shows:
var bBackgroundColor:Boolean=false;
override public function styleChanged(styleProp:String):void {
super.styleChanged(styleProp);
// Check to see if style changed.
if (styleProp=="backgroundColor")
{
bBackgroundColor=true;
invalidateDisplayList();
return;
}
}
The styleChanged() method first calls superclass' styleChanged() method to let the superclass handle the style change.
After the superclass gets a call to handle the style change, your component can detect that the user set the backgroundColor style, and handle it. By handling the style change after the superclass makes the change, you can override the way the superclass handles the style.
Notice that the method calls the invalidateDisplayList() method, which causes Flex to execute the component's updateDisplayList() method at the next screen update. Although you can detect style changes in the styleChanged() method, you still use the updateDisplayList() method to draw the component on the screen. For more information, see Defining a style property.
Typically, you use a flag to indicate that a style changed. In the updateDisplayList() method, you check the flag and update the component based on the new style setting, as the following example shows:
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {
super.updateDisplayList(unscaledWidth, unscaledHeight);
// Check to see if style changed.
if (bBackgroundColor==true)
{
// Redraw the component using the new style.
...
}
}
By using flags to signal style updates to the updateDisplayList() method, the updateDisplayList() method has to perform only the updates based on the style changes; it may not have to redraw or recalculate the appearance of the entire component. For example, if you are changing only the border color of a component, it is more efficient to redraw only the border, rather than redrawing the entire component every time someone changes a style.
When you create a component, you might want to create a style property so that component users can configure it by using styles. For example, you create a component, named StyledRectangle, that uses a gradient fill pattern to define its color, as the following example shows:
This gradient is defined by two colors that you set by using a new style property called fillColors. The fillColors style takes an array of two colors that component users can set. The StyledRectangle.as class defines default colors for the fillColors style, but you can also set them, as the following example shows:
<?xml version="1.0"?>
<!-- skinstyle\MainRectWithFillStyles.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:MyComp="myComponents.*">
<s:layout>
<s:VerticalLayout/>
</s:layout>
<!-- Set style by using a CSS type selector. -->
<fx:Style>
@namespace "myComponents.*";
StyledRectangle {fillColors: #FF00FF, #00FFFF}
</fx:Style>
<!-- By default, use the style defined by the CSS type selector. -->
<MyComp:StyledRectangle id="mySR1"/>
<!-- By default, use the style defined by the CSS type selector. -->
<MyComp:StyledRectangle id="mySR2"/>
<!-- Change the default style by using the setStyle() method. -->
<mx:Button label="Set gradient"
click="mySR2.setStyle('fillColors', [0x000000, 0xFFFFFF]);"/>
<!-- Set fillColors in MXML. -->
<MyComp:StyledRectangle id="mySR3" fillColors="[0x00FF00, 0xFFFFFF]"/>
</s:Application>
In this example, the CSS type selector for the StyledRectangle component sets the initial values of the fillColors property to #FF00FF and #00FFFF. For the second StyledRectangle components, you use the click event of a Button control to change the fillColor style by using the setStyle() method. The third component sets the style property by using an MXML tag attribute.
You define a style property for a component in the class definition.
Insert the [Style] metadata tag that defines the style before the class definition.
You insert the [Style] metadata tag before the class definition to define the MXML tag attribute for a style property. If you omit the [Style] metadata tag, the MXML compiler issues a syntax error when you try to set the property as an MXML tag attribute.
The [Style] metadata tag has the following syntax:
[Style(name="style_name"[,property="value",...])]
For more information, see Metadata tags in custom components.
Override the styleChanged() method to detect changes to the property.
Override updateDisplayList() method to incorporate the style into the component display.
Define a static initializer to set the default value of the style property.
For more information, see Setting default style values.
The following code example defines the StyledRectangle component and the fillColors style. It also defines a second style property named alphas that you can use to set the alpha values of the fill:
package myComponents
{
// skinstyle/myComponents/StyledRectangle.as
import mx.core.UIComponent;
import mx.styles.CSSStyleDeclaration;
import mx.styles.StyleManager;
import flash.display.GradientType;
import mx.core.FlexGlobals;
// Insert the [Style] metadata tag to define the name, type
// and other information about the style property for the
// MXML compiler.
[Style(name="fillColors",type="Array",format="Color",inherit="no")]
[Style(name="alphas",type="Array",format="Number",inherit="no")]
public class StyledRectangle extends UIComponent
{
// Define a static variable.
private static var classConstructed:Boolean = classConstruct();
// Define a static method.
private static function classConstruct():Boolean {
if (!FlexGlobals.topLevelApplication.styleManager.getStyleDeclaration("myComponents.StyledRectangle"))
{
// If there is no CSS definition for StyledRectangle,
// then create one and set the default value.
var myRectStyles:CSSStyleDeclaration = new CSSStyleDeclaration();
myRectStyles.defaultFactory = function():void
{
this.fillColors = [0xFF0000, 0x0000FF];
this.alphas = [0.5, 0.5];
}
FlexGlobals.topLevelApplication.styleManager.setStyleDeclaration("myComponents.StyledRectangle", myRectStyles, true);
}
return true;
}
// Constructor
public function StyledRectangle() {
super();
}
// Define a default size of 100 x 100 pixels.
override protected function measure():void {
super.measure();
measuredWidth = measuredMinWidth = 100;
measuredHeight = measuredMinHeight = 100;
}
// Define the flag to indicate that a style property changed.
private var bStypePropChanged:Boolean = true;
// Define the variable to hold the current gradient fill colors.
private var fillColorsData:Array;
// Define the variable to hold the current alpha values.
private var alphasData:Array;
// Define the variable for additional control on the fill.
// You can create a style property for this as well.
private var ratios:Array = [0x00, 0xFF];
// Override the styleChanged() method to detect changes in your new style.
override public function styleChanged(styleProp:String):void {
super.styleChanged(styleProp);
// Check to see if style changed.
if (styleProp=="fillColors" || styleProp=="alphas")
{
bStypePropChanged=true;
invalidateDisplayList();
return;
}
}
// Override updateDisplayList() to update the component
// based on the style setting.
override protected function updateDisplayList(unscaledWidth:Number,
unscaledHeight:Number):void {
super.updateDisplayList(unscaledWidth, unscaledHeight);
// Check to see if style changed.
if (bStypePropChanged==true)
{
// Redraw gradient fill only if style changed.
fillColorsData=getStyle("fillColors");
alphasData=getStyle("alphas");
graphics.beginGradientFill(GradientType.LINEAR,
fillColorsData, alphasData, ratios);
graphics.drawRect(0, 0, unscaledWidth, unscaledHeight);
bStypePropChanged=false;
}
}
}
}
One of the issues that you have to decide when you create a style property for your component is how to set its default value. Setting a default value for a style property is not as simple as calling the setStyle () method in the component's constructor; you must take into consideration how Flex processes styles, and the order of precedence of styles.
When Flex compiles your application, Flex first examines any style definitions in the <fx:Style> tag, before it creates any components. Therefore, if you call setStyle() from within the component's constructor, which occurs after processing the <fx:Style> tag, you set the style property on each instance of the component; this overrides any conflicting CSS declarations in the <fx:Style> tag.
The easiest way to set a default value for a style property is to define a static initializer in your component. A static initializer is executed once, the first time Flex creates an instance of a component. In Defining a style property, you defined a static initializer, by using the classConstructed variable and the classConstruct() method, as part of the StyledRectangle.as class.
The classConstruct() method is invoked the first time Flex creates a StyledRectangle component. This method determines whether a style definition for the StyledRectangle class already exists, defined by using the <fx:Style> tag. If no style is defined, the classConstruct() method creates one, and sets the default value for the style property.
Therefore, if you omit the <fx:Style> tag from your application, the style definition is created by the classConstruct() method, as the following example shows:
<?xml version="1.0"?>
<!-- skinstyle\MainRectNoStyles.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:MyComp="myComponents.*">
<s:layout>
<s:VerticalLayout/>
</s:layout>
<MyComp:StyledRectangle/>
</s:Application>
If you include the <fx:Style> tag, the <fx:Style> tag creates the default style definition, as the following example shows:
<?xml version="1.0"?>
<!-- skinstyle\MainRectCSSStyles.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:MyComp="myComponents.*">
<fx:Style>
@namespace "myComponents.*";
StyledRectangle {fillColors: #FF00FF, #00FFFF}
</fx:Style>
<MyComp:StyledRectangle/>
</s:Application>
Navigation
Adobe and Adobe Flash Platform are either registered trademarks or trademarks of Adobe Systems Incorporated in the United States and/or other countries and are used by permission from Adobe. No other license to the Adobe trademarks are granted.