`
keren
  • 浏览: 1560122 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

重写(覆盖)UICompent的核心方法

    博客分类:
  • Flex
阅读更多
覆盖核心 UIComponent 方法
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.

本文来源于 冰山上的播客 http://xinsync.xju.edu.cn
原文地址:http://xinsync.xju.edu.cn/index.php/archives/4869
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics