Applying styles to StyleableTextField with Flex CSS

Posted on October 10, 2011 | Comments Off

The following code example comes from my experience in building the Caltrain Times mobile application. In the process of building out Caltrain Times I needed to convert some MXML item renders into ActionScript item renderers. I used some Flex CSS class selectors to change the look and feel for some labels based upon a selected state. I also had variations of font sizes in the Flex CSS class selectors based upon application dpi.

When going from MXML to ActionScript for item renderers or for performance reasons typically you use StyleableTextField instead of Label. StyleableTextField is a TextField with support for a subset of Label styles. StyleableTextField doesn’t support styles through MXML or other typical fashions of the Label class. This means you typically to set the styles explicitly on the StyleableTextField, but then you have to know what styles are valid. There had to be another way. I didn’t want to go through all the Flex CSS class properties I used in the MXML Label versions so I went looking for a solution to apply the styles through use of CSS class selectors. Now this is a solution and it works; but it might have performance implications for different types of content. In general it should work just fine if you are not changing the styles all the time.

Here is a screen shot of the item renderer with its selected state CSS changes.

Caltrain Times CSS applied to ActionScript ItemRenderer


To start I needed to figure out how StyleableTextField.getStyle() works.

public function getStyle(styleProp:String):*
{
    // check out inline style first
    if (_inlineStyleObject && _inlineStyleObject[styleProp] !== undefined)
        return _inlineStyleObject[styleProp];
   
    // check styles that are on us via styleDeclaration
    if (styleDeclaration && styleDeclaration.getStyle(styleProp) !== undefined)
        return styleDeclaration.getStyle(styleProp);
   
    // if not inlined, check our style provider
    if (styleName is IStyleClient)
        return IStyleClient(styleName).getStyle(styleProp);
   
    // if can't find it, return undefined
    return undefined;
}

This lets us know it first checks to see if there is a style assigned to the container object. This didn’t work for me because I have multiple StyleableTextFields in the item renderer that needed different styles, as well as changing one of the StyleableTextFields dynamically. The class then checks for a styleDeclaration property, and if set it uses it to look up the style property value. This was the way I wanted to try out because I could use the Flex CSS class with out setting individual styles on objects.

The following code snippets are available in the com.renaun.caltrain.renderers.StationRendererAS file found in the http://github.com/renaun/CaltrainTimes repo.

Here is the initial setting of the styleDeclaration with the CSS class selector.

override protected function createChildren():void
{
//...
        if (!lblStation)
    {
        lblStation = createLabelDisplay2();
        lblStation.styleDeclaration = styleManager.getStyleDeclaration(".stationText1");
        lblStation.filters = [subtleDropShadow];
    }
//....
}

protected function createLabelDisplay2():StyleableTextField
{
    var lbl:StyleableTextField = StyleableTextField(createInFontContext(StyleableTextField));
    lbl.editable = false;
    lbl.selectable = false;
    lbl.multiline = false;
    lbl.wordWrap = false;
    lbl.antiAliasType = AntiAliasType.ADVANCED;
   
    addChild(lbl);
    return lbl;
}

Then to dynamically change the styles at runtime I do this:

override public function set selected(value:Boolean):void
{
    super.selected = value;
   
//...
   
    lblStation.styleChanged(null);
    lblStation.styleDeclaration =
        styleManager.getStyleDeclaration("."+((!value) ? "stationText1" : "stationText2"));
    lblStation.commitStyles();

//...
   
    invalidateDisplayList();
}

The lblStation.styleChanged(null); line of code sets the invalidateStyleFlag to true. This has to be done to allow styles to be set once lblStation.commitStyles(); is called.

This approach provides you with the ability to set various Flex CSS class selectors for different StyleableTextFields in your ActionScript item renderers. As well as let you change them up when you want.