I need to build a new UI control based on UIComponent. The control's height should have a certain ratio to the width and also depends on what content is shown (amount of text inside). Could anybody recommend how I should do this?
I have tried googling around, but it seems all articles just try to avoid talking about the case. My personal feeling is that the way Flex renders, i.e. invalidate and update display list, is natively inefficient to deal with the situation.
Below are my codes. It works all fine, but it seems this is not the most efficient way because the height is calculated inside updateDisplayList(), which triggers another updateDisplayList().
The control is used inside a mobile project, so when the device is rotated, the parent's size will be changed and the control needs to be resized as well.
So, a few questions:
- What should I do in measure()? Since the height is based on actual width, I cannot get the final width until updateDisplayList(), because the parent of the control has width defined as percentage.
- Is it correct to calculate the height at the very beginning of updateDisplayList()? If not, how should I do it?
Below is an example what I mean.
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import mx.core.UIComponent;
public class MyControl extends UIComponent
{
public function MyControl()
{
super();
}
public var textPadding:Number = 15;
public var heightRatio:Number = 1.61803398875;
private var _label:String;
private var labelChanged:Boolean = false;
public function get label():String
{
return _label;
}
public function set label(value:String):void //can be long text with about 20-30 lines
{
if (_label != value)
{
_label = value;
labelChanged = true;
invalidateProperties();
invalidateSize();
invalidateDisplayList();
}
}
private var text:TextField;
override protected function createChildren():void
{
super.createChildren();
if (!text)
{
text = new TextField();
text.autoSize = TextFieldAutoSize.LEFT;
text.multiline = true;
text.wordWrap = true;
addChild(text);
}
}
override protected function commitProperties():void
{
super.commitProperties();
if (labelChanged)
{
text.text = label;
labelChanged = false;
}
}
override protected function measure():void
{
super.measure();
//What should I do here?
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
text.width = unscaledWidth;
if (text.height < unscaledWidth / heightRatio)
{
height = unscaledWidth / heightRatio + textPadding * 2;
}
else
{
height = text.height + textPadding * 2;
}
super.updateDisplayList(unscaledWidth, unscaledHeight);
text.x = textPadding;
text.y = textPadding;
}
}