以像素为单位的字符串长度

时间:2011-01-07 17:27:20

标签: actionscript-3 string fonts drop-down-menu flex4

我正在使用arrayCollection字符串填充dropDownList。我希望下拉列表控件的宽度与数组集合中最长字符串的大小(以像素为单位)匹配。我面临的问题是:集合中字符串的字体宽度不同,例如: 'W'看起来比'l'宽。所以我估计一个字符的宽度为8像素,但这不是很整洁。如果遇到具有许多“W”和“M”的字符串,则估计是错误的。所以我想要精确的字符串像素宽度。如何获得字符串的确切长度?

我的解决方案是将所有字符估计为8像素宽,如下所示:

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);
   }

任何想法或解决方案都受到高度重视。

由于

4 个答案:

答案 0 :(得分:7)

要获得更准确的度量,可以使用字符串填充TextField,然后测量该TextField文本的宽度。

代码:

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);
}

用法:

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);

答案 1 :(得分:1)

我没有对其他人的帖子进行编辑权限,所以我将其作为一个单独的答案发布,但是如果有效的话应该归功于Cameron:

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);
}

如果我发现它确实存在并且他已被编辑,我会删除这个以保持清洁。

很抱歉垃圾邮件最初是试图回答这个错误的问题...无论如何测试这个,它似乎工作。我在Flex中做了这个,但你应该能够只使用AS3部分没有问题我只是在UIComponent中包装文本字段以使其在舞台上使用但是使用自动调整大小似乎工作正常:

<?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>

答案 2 :(得分:0)

这是上述某些代码的更精美版本。考虑换行符(html break和\ n)并使用其他一些优化使创建的Textfield对象无效。希望这有用。

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 );

如果你喜欢上课,请在我的GIT框架中查看: https://github.com/charlesclements/as3-tools/blob/master/net/charlesclements/util/text/TextUtil.as

AS3-工具:https://github.com/charlesclements/as3-tools

另外,我们的Flash / JS兄弟Jack Doyle @ GreenSock有一些方便的操作文本。非常值得一试:http://www.greensock.com/splittext/

答案 3 :(得分:0)

这是我为Java编写的例程。我想您可以将其转换为Javascript或其他任何形式。

这不是精确的,但给出了大概的答案。假定空间大约为200宽,而M和W大约为1000宽。显然,您需要根据您的特定字体大小进行缩放。

static int picaSize(String s)
{
    // the following characters are sorted by width in Arial font
    String lookup = " .:,;'^`!|jl/\\i-()JfIt[]?{}sr*a\"ce_gFzLxkP+0123456789<=>~qvy$SbduEphonTBCXY#VRKZN%GUAHD@OQ&wmMW";
    int result = 0;
    for (int i = 0; i < s.length(); ++i)
    {
        int c = lookup.indexOf(s.charAt(i));
        result += (c < 0 ? 60 : c) * 7 + 200;
    }
    return result;
}