2011-01-07 20 views
7

Estoy rellenando un dropDownList con arrayCollection de cadenas. Quiero que el ancho del control de la lista desplegable coincida con el tamaño (en píxeles) de la cadena más larga de la colección de matriz. El problema al que me enfrento es: el ancho de la fuente de las cadenas en la colección es diferente, p. 'W' parece más ancho que 'l'. Así que calculé que el ancho de un personaje es de 8 píxeles, pero eso no es muy bonito. Si se encuentra una cadena que tiene muchas 'W' y 'M', la estimación es incorrecta. Así que quiero un ancho de píxel preciso de las cadenas. ¿Cómo puedo obtener la longitud exacta de una cadena en píxeles?Longitud de una cadena en píxeles

Mi solución que estima todos los caracteres a ser de 8 píxeles de ancho se da a continuación:

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

Cualquier idea o solución es muy valorada.

Gracias

Respuesta

7

Para obtener una medición más precisa, puede instalar en un campo de texto con la cadena, luego medir la anchura del texto de ese campo de texto.

Código:

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

Uso:

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

@Rose Cree que necesita agregar una llamada validateNow() después de asignar la cadena, pero antes de comprobar el texto Ancho/textoAlta la asignación de la cadena provoca la invalidación del tamaño pero el recálculo del tamaño no es síncrono, por lo que debe forzar la validación – shaunhusain

+0

¡Genial! Me gustó la solución; tengo un pequeño problema sin embargo. No está obteniendo el ancho de píxel correcto. Le di esta cadena en la matriz. var strings: Array = ["a", "jirafa", "foo", "El objeto ArrayCollection no representa ninguno"]; Ahora tiene el ancho de texto en 245, pero de hecho el tamaño era 276. Entonces aparece una barra de desplazamiento en mi lista desplegable.De su código eliminé la parte que tiene textFormat, así que hice que la función measureStr sea una función de argumento – Rose

+0

@Rose: The TextFormat afecta la fuente (-face y -family) que se usa al medir el texto - debe cambiarse para que coincida exactamente con el de la lista desplegable (aunque no estoy seguro de qué es eso). Después de eliminar el material textFormat, ¿le da la longitud correcta? Si es así, sospecho que es porque el formato de texto predeterminado es el mismo que el que se está usando en la lista desplegable. – Cameron

1

no tengo editar priv sobre de correos de otras personas, así que estoy publicar esto como una respuesta por separado pero el crédito debe ir a Cameron si esto funciona:

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

Si veo que lo hace y se edita, lo eliminaría por limpieza.

Lo siento por el mensaje de basura que inicialmente intentaba responder la pregunta simplemente lo hizo de forma errónea ... de todos modos probado este y parece que funciona. Hice esto en Flex, pero usted debería ser capaz de utilizar sólo la parte AS3 ningún problema que acaba de terminar el campo de texto en un UIComponent conseguirlo en el escenario, pero utilizando el tamaño automático parece funcionar bien:

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

pero ¿la clase textField tiene el método validateNow() ?? http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/text/TextField.html?filter_flex=4.1&filter_flashplayer=10.1&filter_air=2 – Rose

+0

¡Doy! Lo siento, me adelanté allí, así que estoy acostumbrado a usar validateNow en estos escenarios ... es muy probable que TextField sea un componente de Flash, no uno de Flex, el esquema de validación del que estaba hablando se aplica en los componentes de Flex ... Tengo hecho esto con un campo de texto, aunque también cree que puede necesitar establecer el tamaño automático o algo similar ... publicará una edición anterior en unos minutos – shaunhusain

+0

Interesante ... ¿Está seguro de que es el 'autoSize' haciéndolo y no el hecho de que el cuadro de texto se está agregando al escenario? – Cameron

0

Este es una versión más pulida de algunos de los códigos anteriores. Contabilización de saltos de línea (html break y \ n) y anulación del objeto Textfield creado con algunas otras optimizaciones. Espero que esto sea útil.

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

Si prefiere esto en una clase, comprobar que en mi marco GIT: https://github.com/charlesclements/as3-tools/blob/master/net/charlesclements/util/text/TextUtil.as

AS3-herramientas: https://github.com/charlesclements/as3-tools

Además, nuestro Flash/hermano JS Jack Doyle @ GreenSock tiene algunas cosas útiles para hacer con la manipulación de texto. Vale la pena comprobarlo: http://www.greensock.com/splittext/

Cuestiones relacionadas