2011-01-07 43 views
7

Sto popolando un dropDownList con arrayCollection di stringhe. Voglio che la larghezza del controllo elenco a discesa corrisponda alla dimensione (in pixel) della stringa più lunga nella raccolta di array. Il problema che sto affrontando è: la larghezza del carattere delle stringhe nella collezione è diversa, ad es. 'W' sembra più largo di 'l'. Quindi ho stimato che la larghezza di un personaggio sia di 8 pixel, ma non è molto carina. Se si incontra una stringa con molti "W" e "M", la stima è errata. Quindi voglio una larghezza di pixel precisa delle stringhe. Come posso ottenere la lunghezza esatta di una stringa in pixel ??Lunghezza di una stringa in pixel

La mia soluzione che stima tutto il carattere per essere di 8 pixel di larghezza è il seguente:

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

Qualsiasi idea o la soluzione è molto apprezzato.

Grazie

risposta

7

Per ottenere una misurazione più accurata, è possibile compilare un TextField con la stringa, quindi misurare la larghezza del testo di quel TextField.

Codice:

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

@Rose Credere che è necessario aggiungere una chiamata validateNow() dopo aver assegnato la stringa ma prima di controllare il testoWidth/textHeight l'assegnazione della stringa causa l'invalidazione della dimensione ma il ricalcolo della dimensione non è sincrono quindi devi forzare la validazione – shaunhusain

+0

Grande! Mi è piaciuta la soluzione; ho un piccolo problema però Non sta ottenendo la giusta larghezza di pixel. Gli ho dato questa stringa nell'array. var stringhe: Array = ["a", "giraffe", "foo", "L'oggetto ArrayCollection non rappresenta alcun"]; Ora la larghezza di testo era 245 ma in realtà la dimensione era 276. Quindi una barra di scorrimento viene visualizzata nell'elenco a discesa.Dal tuo codice ho rimosso la parte che ha textFormat, quindi ho reso la funzione measureStr una funzione a 1 argomento – Rose

+0

@Rose: Il TextFormat influisce sul carattere (-face e -family) che viene utilizzato quando si misura il testo - dovrebbe essere cambiato per abbinare esattamente quello dell'elenco a discesa (anche se non sono sicuro di cosa sia). Dopo aver rimosso la proprietà textFormat, indica la lunghezza giusta? Se è così, ho il sospetto che sia perché il formato di testo predefinito è lo stesso di quello che viene utilizzato nell'elenco a discesa. – Cameron

1

Non ho modificare priv su di posta di altre persone in modo da sto postando questo come una risposta separata, ma di credito dovrebbe andare a Cameron se questo funziona:

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

Se vedo che lo fa e la sua è curato mi piacerebbe cancellare questo uno per la pulizia.

Ci scusiamo per il post di immondizia inizialmente stava cercando di rispondere alla domanda appena fatto in modo errato ... comunque testato questo e sembra funzionare. Ho fatto questo in Flex, ma si dovrebbe essere in grado di utilizzare solo la parte AS3 nessun problema che ho appena concluso il campo di testo in un UIComponent per farlo sul palco, ma utilizzando l'autosize sembra funzionare bene:

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

ma la classe textField ha metodo 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! scusa mi sono abituato a usare validateNow in questi scenari ... è molto probabile che TextField sia un componente Flash non Flex, lo schema di validazione di cui parlavo si applica ai componenti Flex ... Ho fatto questo con un campo di testo anche se credete che potrebbe essere necessario impostare la dimensione automatica o qualcosa del genere ... pubblicherà una modifica in alto in pochi minuti – shaunhusain

+0

Interessante ... Sei sicuro che sia il 'autoSize' a farlo e non il fatto che la casella di testo viene aggiunta allo stage? – Cameron

0

Questo è una versione più raffinata di alcuni dei codici precedenti. Contabilizzazione per interruzioni di riga (html break e \ n) e annullando l'oggetto Textfield creato con alcune altre ottimizzazioni. Spero che questo sia utile.

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

Se si preferisce questo in una classe, check it out nel mio quadro GIT: https://github.com/charlesclements/as3-tools/blob/master/net/charlesclements/util/text/TextUtil.as

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

Inoltre, il nostro Flash/fratello JS Jack Doyle @ Greensock ha alcune cose utili da fare con la manipolazione del testo. Ne vale la pena di verificarlo: http://www.greensock.com/splittext/

Problemi correlati