Home > Best Practices, Flex, tutorial > Overriding core UIComponent Methods

Overriding core UIComponent Methods

February 19th, 2009

Whenever I am working on a Flex project, it is quite seldom that I have been able to take an out of the box component and have it do EXACTLY what I need to do (barring something like a Label). Sometimes I need to create a container component to use as an itemrenderer for a grid. However, sometimes it is not as easy as whipping up some mxml tags to layout what we need. Luckily though, there are 5 methods that every UIComponent implements* that we are able to override and manipulate our objects as we wish. These methods are createChildren, commitProperties, measure, layoutChrome and updateDisplayList. I will be giving a brief explaining of what they are and why we would override them. After that, I will be discussing the flags within UIComponent.as that call these functions and some things to watch out for when overriding these functions.


createChildren

override protected function createChildren():void{
    super.createChildren();
    if (!_button){
        _button = new Button();
        _button.addEventListener(MouseEvent.CLICK,handleEvent);
        _button.setStyle("color",0xFF0000);
        addChild(_button);
    }
}

By far the easiest to explain, createChildren does just that. This method is pretty much used to add the children of the component. Aside from that, you are able to set some default settings, event listeners and styles.

commitProperties

override protected function commitProperties():void {
 super.commitProperties();
    if (dataChanged){
        isDirty=true;
    }
}

When I have used this, I have used it to set state specific properties of my component. IE: changing the color depending on a value, setting flags, etc. Also if your component implements IListItemRenderer or IDropInListItemRenderer, your data or listData values will be set by the time they your component reaches commitProperties.

measure

override protected function measure():void {
    super.measure();
    this.measuredHeight=16;
    this.percentWidth=100;
    this.minHeight=5;
}

The Measure function is about as easy to explain as creareChildren. Within here, you are able to set your components default height/width, as welll as minimum/maximum height/width. However, the way this function gets called is a little unique when compared to the other functions, while I will discuss in a bit.

layoutChrome

override protected function layoutChrome(unscaledWidth:Number,unscaledHeight:Number):void{
    if(border){
        border.setActualSize(w,h);
    }
}

layoutChrome is used to set the boarders of any Container class that you are extending off of. If any of these functions was the forgotten stepchild, it is this function. I have only run into a situation once where I needed to implement it. However, the one time I got to use it, I pulled my hair out because I ran into an instance where Adobe wanted to protect me and I had to use the mx_internal namespace.

updateDisplayList

override protected function updateDisplayList(unscaledWidth:Number,unscaledHeight:Number):void{
    super.updateDisplayList(unscaledWidth,unscaledHeight);
    var o:Object;
    var yOffset=10;
    for (var x:int=0;x<numChildren;x++){
        o = getChildAt(x);
        yOffset += o.height;
        o.move(o.x+OFFSET,yOffset);
    }
}

If layoutChrome is the forgotten step child, updateDisplayList is the most popular child, and for good reason. This is the component that sets its position and size (if need be) and the component will not be displayed until it is called. For container objects that have more than one component, this is the function that allows you to manually position those components based off of its current state. A perfect example of this would be an HBox of VBox. Your components are positioned horizontally or vertically within updateDisplayList.

With these five functions, you will be able to create any componet that you can think of. But what calls these functions? Turns out that within UIComponent, there are three flags which are set by these functions:

invalidateProperties()
When this is called, it marks your component to call commitProperties upon the next render update.
invalidateDisplayList()
When this is called, it will call both layoutChrome, as well as updateDisplayList.
invalidateSize()
This is the interesting one. Calling this method will mark the measure() function to be called, but there is one slight variation on this one. If I update the x value on a component, it will be marked as invalid and updateDisplayList will be called upon the next render event. If a data event gets fired, its marked as invalid and commitProperites is called. However, if I change the height, measure will not be called. Flex will only call measure() if you set explicitHeight or explicitWidth to NaN.

What to watch out for
When people implement these functions, sometimes they do not realize the power they have taken responsibility of. They are to be treated with the respective they deserve. First, do not forget to call the super method of each functions. That may drop you in the land of some angry times if you dont. Another thing I have seen is people sometimes get tempted to add children inside of something like commitProperties or updateDisplayList. This may cause serious performance issues. Whenever addChild is called, invalidateProperties and invalidateDisplayList is called, creating a big mess. It is best to use these functions for only their intended purpose.

It is hard to be a Flex programmer with out having to dive into to the world of creating your own components. Out of the box functionality often does not give us what we need. With these functions, you will be able to create any component you need from the ground up.

*Layoutchrome is included in anything that extends the Container class. A large number of components utilize this, but UIComponent does not.

Best Practices, Flex, tutorial ,

  1. February 20th, 2009 at 14:55 | #1

    Great article! Thank you very much.

  2. March 17th, 2009 at 16:36 | #2

    Calling addChild() in commitProperties() is quite common when the children are created based on the properties that are passed to the component. For instance, anything with item renderers must create its children in commitProperties() or maybe even updateDisplayList() because you probably won’t know how many children you need until you have some data or even the dimensions of the component. I wouldn’t say this is too strange. Obviously, if a specific number of children need to exist throughout the entire life of the component, then yes, absolutely, create them in createChildren().

  1. No trackbacks yet.