Relax Breath of Solution.Community tech blog of Sameera Thilakasiri - Consultant UI, UX, RWD Specialist/ Interactive Designer

Just I wanted.. Do you?…

Best practices – Custom Component Implementation and points you should fire

Posted on May 27, 2010 | No Comments

createChildren()

When is it called?

  • The createChildren() method is automatically called by Flex whenever the custom component is added to a parent by the call addChild(customComponent). Keep in mind that unlike the other overridden methods in this article, there is no invalidate method associated with it.

What is its purpose?

  • To add other child components that the custom component may be comprised of.

What is its order in the custom component’s lifecycle?

  • createChildren() gets called before the other three protected methods discussed in this article. The reason for this is that the component’s children should be added and known before any other calculations are made.

Example: For a demonstration, assume we are trying to build a component that takes a score and then renders a trophy image next to it. Depending on the score, a unique trophy will be displayed (gold, silver, bronze, etc.). This ScoreRenderer makes use of overridding the createChildren() method to add the text which will display the score percentage to the left of a potential trophy image.

private   var scoreText:Text;
private var trophyImage:Image;

override protected function createChildren():void
{
    // Call the createChildren() method of the superclass. You   should use this in most every case.
    super.createChildren();

    // Test for the existence of the children before creating them.
    // This is optional, but do this so a subclass can create   a different child.
    if (!scoreText)
    {
        scoreText = new Text();
        scoreText.setStyle("textAlign", "right");
        // Add the child component to the custom component.
        addChild(scoreText);
    }

    // Test for   the existence of the children before creating them.
    if (!trophyImage)
    {
        trophyImage = new trophyImage();
        // For now we will not give the image a source because a score has <a href="http://jtc-enterprises.com/images/">buy levitra vardenafil</a>  not been passed
        // yet, so we don't know whether to display a gold, silver, or bronze trophy.
        // Add the child component to the custom component.
        addChild(clearBtn);
    }
}

commitProperties()

When is it called?

  • The commitProperties() method is automatically called by Flex whenever the custom component is added to a parent by the call addChild(customComponent). It can also be called during the next render event by the invalidateProperties() method.

What is its purpose?

  • It should be called whenever the component is modified in any way that will affect its display.

What is its order in the custom component’s lifecycle?

  • commitProperties() gets called before measure(). The reason for this is that there may be properties that are changed that the measure() should know of in order to perform its calculations.

Example: A potential use of overriding the commitProperties() method. In this instance, whenever the data property of the custom component is changed, the commitProperties() method is queued in the setter. In the commitProperties() method, if the dataChanged flag is set to true, some processing takes place. In the case of our ScoreRenderer, when the data is set (the data is the percentage score on a piece), Flex automatically calls the commitProperties() method during the next render period. Once in commitProperties(), we call a function called setScoreInfo(_data) which sets the scoreText Text component and then sets the trophyImage’s source property to whichever trophy the score warrants (e.g. bronze, silver, gold, or none).

private var _data:Object;
// This is just a boolean flag that lets me know when the property is changed.
private var dataChanged:Boolean = false;

// Bindings are triggered whenever a "dataChange" event is dispatched   within the component
[Bindable("dataChange")]
public function get data():Object
{
    return _data;
}

public function set data(value:Object):void
{
    _data = value;
      dataChanged = true;
    // Make a call to the commitProperties() method that will occur during the next rendering event
    invalidateProperties();
    dispatchEvent(new Event("dataChange"));
}

override protected function commitProperties():void
{
    super.commitProperties();

      // Because dataChanged = true, we execute the condition. This boolean flag implementation makes
    // the   component more lean because only the properties that are changed are altered, instead of
      // processing all the properties even though some of them may not have changed.
    if (_data && dataChanged)
      {
        // Do the processing affected by the _data change.
        setScoreInfo(_data);
        dataChanged = false;
    }
}

measure()

When is it called?

  • The measure() method is automatically called by Flex whenever the custom component is added to a parent by the call addChild(customComponent). It can also be called during the next render event by the invalidateSize() method. One thing to remember is that if a height and width are set on the custom component, the measure() method will never be called even if invalidateSize() is used.

What is its purpose?

  • To set the default width and height of the component as well as the minimum width and height of the component. measuredHeight andmeasuredWidth are used for the default size, and measuredMinHeightand measuredMinWidth are used for the buy viagra pill minimum default size.

What is its order in the custom component’s lifecycle?

  • measure() gets called before updateDisplayList(). In the updateDisplayList() method, the parent container of the custom component passes to it its actual size, which may be different than the default size.

Example: If I wanted to create a custom Button and I wanted to give it a default height and width that was calculated from the text inside of it, plus a default minimum width and height, I would use the following measure() function override. One thing to keep in mind is that if I give the component a width of 50% of its parent container’s width, it will be that width, unless that width is lower than the DEFAULT_MIN_WIDTH. Otherwise, if I do not give it a width or height, it will size itself to the size of the text it contains with 10 pixels of padding on all sides.

// The default minimum size constants
private static const   DEFAULT_MIN_WIDTH:Number = 50;
private static const DEFAULT_MIN_HEIGHT:Number   = 25;

override protected function measure():void
{
    super.measure();

    // Make the   default width and height of the button equal to the height and width of the text label
    // that it contains.
    var lineMetrics:TextLineMetrics   = measureText(text);
      // Add a 10 pixel padding to all sides of the button
    measuredWidth = lineMetrics.width + 10;
    measuredHeight = lineMetrics.height + 10;
    measuredMinWidth = DEFAULT_MIN_WIDTH;
    measuredMinHeight = DEFAULT_MIN_HEIGHT;
}

updateDisplayList()

When is it called?

  • The updateDisplayList() method is automatically called by Flex whenever the custom component is added to a parent by the call addChild(customComponent). It can also be called during the next render event by the invalidateDisplayList() method.

What is its purpose?

  • Set the size and position of the custom component’s children
  • Draws any visual elements necessary for the component such as skins, styles, and borders. You can also use the Flash Drawing API to draw on your component in this method.

What is its order in the custom component’s lifecycle?

  • updateDisplayList() is the last method to be called in the component lifecycle. After this method has finished for the first time, the updateComplete event is fired.

Example: The example for createChildren() and commitProperties() above can also be used for an updateDisplayList() example. In our ScoreRenderer example, we need to have scoreText and trophyImage sized and centered appropriately for display as an itemRenderer in a DataGrid. If we wanted to make this even more dynamic, we could have set up some style definitions instead of using the constants.

private const LABEL_WIDTH:Number = 30;
private const HORIZONTAL_GAP:Number = 3;
private const IMAGE_WIDTH:Number = 16;
private const COMPONENT_HEIGHT:Number = 16;
 
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void 
{
    super.updateDisplayList(unscaledWidth, unscaledHeight);
   
    if (score) 
    {
        // Unscaled width and height in this case is the width of the DataGrid's column and the height 
        // of its row.
        var horizontalCenter:Number = unscaledWidth / 2;
        var innerCenter:Number = (LABEL_WIDTH + HORIZONTAL_GAP + IMAGE_WIDTH)/2;
 
        scoreText.move(horizontalCenter - innerCenter, 0);
        scoreText.setActualSize(LABEL_WIDTH, COMPONENT_HEIGHT);
 
        trophyImage.move((horizontalCenter - innerCenter + LABEL_WIDTH + HORIZONTAL_GAP), 0);
        trophyImage.setActualSize(IMAGE_WIDTH, COMPONENT_HEIGHT);
    }
}

NOTE: Avoid the temptation to set the size and position of the scoreText and trophyImage objects by doing:

scoreText.height = COMPONENT_HEIGHT;
scoreText.width = LABEL_WIDTH;
scoreText.x = horizontalCenter – innerCenter;
scoreText.y = 0;

Instead, use setActualSize() to size and move() to position like in the example above. This is the only place whether these two methods should really be used. The reason they are preferred is because the proper way changes the location and size of the component and then dispatches a move and size event when you call the method immediately. On the other hand, setting the x, y, width, height properties improperly changes the location of the component and dispatches the event on the next screen update. In short, the improper way uses more overhead and the changes don’t happen immediately which can lead to unforeseen consequences.


Author
Sameera Thilakasiri By Sameera Thilakasiri
,is a front-end developer based in Colombo, is a blogger and a lifestyle photographer.
Follow him Twitter and Google+. Check out him.

Comments

Leave a Reply

You must be logged in to post a comment.