I'm populating a dropDownList with arrayCollection of strings. I want the width of the drop down list control to match with the size (in pixels) of the longest string in the array collection. The problem I'm facing is: the font width of the strings in the collection are different e.g. 'W' looks wider than 'l'. So I estimated the width of a character to be 8 pixels but that's not pretty neat. If a string that has many 'W' and 'M' is encountered the estimation is wrong. So I want precise pixel width of strings. How can i get the exact length of a string in pixels??
My solution that estimates all character to be 8 pixels wide is given below:
public function populateDropDownList():void{
var array:Array = new Array("o","two","three four five six seven eight wwww");
var sampleArrayCollection:ArrayCollection = new ArrayCollection(array);
var customDropDownList:DropDownList = new DropDownList();
customDropDownList.dataProvider=sampleArrayCollection;
customDropDownList.prompt="Select ...";
customDropDownList.labelField="Answer Options:";
//calculating the max width
var componentWidth=10; //default
for each(var answerText in array){
Alert.show("Txt size: "+ answerText.length + " pixels: " + answerText.length*9);
if(answerText.length * 8 > componentWidth){
componentWidth=answerText.length * 8;
}
}
customDropDownList.width=componentWidth;
answers.addChild(customDropDownList);
}
Any idea or solution is highly valued.
Thanks
To get a more accurate measurement, you can populate a TextField with the string, then measure the width of that TextField's text.
Code:
function measureString(str:String, format:TextFormat):Rectangle {
var textField:TextField = new TextField();
textField.defaultTextFormat = format;
textField.text = str;
return new Rectangle(0, 0, textField.textWidth, textField.textHeight);
}
Usage:
var format:TextFormat = new TextFormat();
format.font = "Times New Roman";
format.size = 16;
var strings:Array = [ "a", "giraffe", "foo", "!" ];
var calculatedWidth:Number = 50; // Set this to minimum width to start with
for each (var str:String in strings) {
var stringWidth:Number = measureString(str, format).width;
if (stringWidth > calculatedWidth) {
calculatedWidth = stringWidth;
}
}
trace(calculatedWidth);
I don't have edit priv on other people's post's so I'm posting this as a separate answer but credit should go to Cameron if this works:
function measureString(str:String, format:TextFormat):Rectangle {
var textField:TextField = new TextField();
textField.autoSize = TextFieldAutoSize.LEFT;
textField.defaultTextFormat = format;
textField.text = str;
return new Rectangle(0, 0, textField.textWidth, textField.textHeight);
}
If I see that it does and his is edited I'd delete this one for cleanliness.
Sorry for the garbage post initially was trying to answer the question just did so erroneously... anyhow tested this one and it appears to work. I did this in Flex but you should be able to just use the AS3 part no problem I just wrapped up the textfield in a UIComponent to get it on stage but using the autosize seems to work fine:
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.core.UIComponent;
protected function textinput1_changeHandler(event:TextOperationEvent):void
{
// TODO Auto-generated method stub
var rect:Rectangle = measureString(event.target.text);
holderBox.graphics.clear();
holderBox.graphics.beginFill(0xFF0000);
holderBox.graphics.drawRect(rect.x,rect.y,rect.width,rect.height);
}
private function measureString(str:String):Rectangle {
var textField:TextField = new TextField();
textField.autoSize = TextFieldAutoSize.LEFT;
textField.text = str;
var uiComponent:UIComponent = new UIComponent();
uiComponent.addChild(textField);
holderBox.addChild(uiComponent);
return new Rectangle(0, 0, textField.textWidth, textField.textHeight);
}
]]>
</fx:Script>
<mx:VBox>
<s:TextInput text="" change="textinput1_changeHandler(event)"/>
<mx:Box id="holderBox"/>
</mx:VBox>
</s:Application>
This is a more polished version of some of the above code. Accounting for linebreaks (html break and \n) and nullifying the created Textfield object with some other optimizations. Hope this is helpful.
function measureString(str:String, font:String="Times New Roman", size:Number=12):Rectangle
{
var textField:TextField = new TextField();
textField.defaultTextFormat = new TextFormat( font, size );
textField.border = true;
textField.multiline = true;
textField.autoSize = TextFieldAutoSize.LEFT;
textField.htmlText = str;
// Grab with and height before nullifying Textfield.
var w:Number = textField.textWidth;
var h:Number = textField.textHeight;
//addChild( textField );// This will add the Textfield to the stage so you can visibly see it.
//if( contains( textField ) ) removeChild( textField );// If it exists onstage, remove it.
textField = null;//nullify it to make it available for garbage collection.
return new Rectangle(0, 0, w, h);
}
var str:String = "Jeremy is a good boy.<br>He also has a red bike. \nSometimes Jeremy rides his bike to the store to buy bread for his family.<br>He likes wholewheat.";
trace( measureString( str, "Times New Roman", 25 ).width );
If you prefer this in a class, check it out in my GIT framework: https://github.com/charlesclements/as3-tools/blob/master/net/charlesclements/util/text/TextUtil.as
AS3-tools:https://github.com/charlesclements/as3-tools
Also, our Flash/JS brother Jack Doyle @ GreenSock has some handy stuff to do with manipulating text. Well worth it to check it out:http://www.greensock.com/splittext/
来源:https://stackoverflow.com/questions/4628368/length-of-a-string-in-pixels