I think I've discovered the problem (but no solution yet). It just occurred to me that the difference between what I see on screen (179 x 138) and what trace() is telling me (134 x 108) is precisely 45 x 30. Since I'm drawing the bubble exactly 45 x 30 pixels larger than the label, I did a trace() of only the label's width/height, and sure enough it is 134 x 108. So, for some odd reason, it seems Flex is not considering what I draw with the Graphics API when it calculates the width/height of the entire component. Is this a bug? If not, how can I coax Flex into giving me the width/height of the entire component?
Similar problem here. I am setting the component's width/height in the measure() method, but the component's height/width properties are always 0 when they are traced. Is this a bug?
It is not recommended to set width/height in measure(). See the documentation on custom components and how commitProperties/measure/updateDisplayList work.
Really? Based on everything I've read so far, the measure() method is where the component's default width/height is defined.
I've determined that in order to read the component's width/height properties, I must do so after it's creationComplete event fires. Even though within the component itself, I can trace the component's measuredHeight & measuredWidth properties and they are valid immediatedly after the component is added to the DisplayList, the parent does not see them. Does that sound right?
My component won't ever change size actually, so should I be setting it's maxWidth & minWidth properties too?
Measure() should only provide measuredWidth/Height and measuredMinWidth/Height. Later, in updateDisplayList(), each parent calls setActualSize or setLayoutBoundsSize on its children to give them their sizes (so they can apply sizes to their children). Only then is the width/height valid.
Setting width/height any sooner locks in the size of the component prevent resizing if needed to shrink or grow to fit in. It can also cause the parent to have to stop and re-measure which will be a drag on performance.
You only need to set maxWidth/Height if the layout is going to try to stretch them.
Maybe I mist-stated what I was doing... here is one of my custom components. Does it look correct?
public class Tab extends UIComponent
private var _tabName:String;
private var _tabNameChanged:Boolean;
private var _labelTextfield:TextField;
private var _bkgrndShape:Shape;
private var _bkgrndColor:uint;
private var _bkgrndColorChanged:Boolean;
private var _tabType:String;
private var _textFormat:TextFormat;
public function Tab()
_bkgrndColor = LayoutConstants.TAB_ACTIVE_COLOR;
override protected function createChildren():void
_bkgrndShape = new Shape();
_bkgrndShape.graphics.lineTo(LayoutConstants.TAB_WIDTH - 10, -44);
_textFormat = new TextFormat();
_textFormat.color = "0x000000";
_textFormat.font = LayoutConstants.UI_BOLD_FONT;
_textFormat.bold = true;
_textFormat.size = 12;
_textFormat.align = TextFormatAlign.CENTER;
_labelTextfield = new TextField();
_labelTextfield.selectable = false;
_labelTextfield.mouseEnabled = false;
_labelTextfield.wordWrap = true;
_labelTextfield.autoSize = TextFieldAutoSize.CENTER;
override protected function commitProperties():void
_labelTextfield.text = _tabName;
_tabNameChanged = false;
var colorTransform:ColorTransform = new ColorTransform();
colorTransform.color = _bkgrndColor;
_bkgrndShape.transform.colorTransform = colorTransform;
_bkgrndColorChanged = false;
override protected function measure():void
measuredWidth = _bkgrndShape.width;
measuredHeight = _bkgrndShape.height;
measuredMinHeight = _bkgrndShape.height;
measuredMinWidth = _bkgrndShape.width;
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
_labelTextfield.x = (unscaledWidth / 2) - (_labelTextfield.width / 2);
_labelTextfield.y = -(unscaledHeight / 2) - (_labelTextfield.height / 2);
public function get tabName():String
public function set tabName(value:String):void
_tabName = value;
_tabNameChanged = true;
public function get tabType():String
public function set tabType(value:String):void
_tabType = value;
public function set bkgrndColor(value:uint):void
_bkgrndColor = value;
_bkgrndColorChanged = true;
Seems like your measure() method isn’t taking into account the textfield and the background shape?
Hmm... not sure I follow you. The textfield sits on top of the background image, so the measure() method just sets the size of the component to the size of the shape.
Maybe I don’t understand what you are looking for. You are apparently not the original poster?
I also noticed you seem to be drawing the background shape into negative coordinates.
I guess the question is, at what point after a custom componnent has been added to the display list using the addElement method can it's width & height properties be accessed and valid values be returned? Immediately querying the component's width and height does not work.
Unless the child has been given an explicit width and height by having those properties set directly, because parents size and position their children a child’s width/height is not known until the parent component has completed its updateDisplayList call. There is no event for that, but an updateComplete event should follow shortly and can be forced by calling validateNow on the parent or one of its parents that have enough information to determine the width and height.