2011-01-07 19 views
7

Wprowadzam dropDownList z arrayCollection of string. Chcę, aby szerokość kontrolki listy rozwijanej była zgodna z rozmiarem (w pikselach) najdłuższego ciągu w kolekcji tablic. Problem z którym stoję, to: szerokość czcionki łańcuchów w kolekcji jest różna. "W" wygląda szerzej niż "l". Tak więc oszacowałem szerokość znaku na 8 pikseli, ale to nie jest miłe. Jeśli napotkasz łańcuch, który ma wiele "W" i "M", szacowanie jest błędne. Dlatego potrzebuję dokładnej szerokości piksela ciągów. Jak mogę uzyskać dokładną długość napisu w pikselach?Długość ciągu w pikselach

Moje rozwiązanie, które szacuje się cały charakter 8 pikseli szerokości podana jest poniżej:

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

Każdy pomysł lub rozwiązanie jest wysoko cenione.

Dzięki

Odpowiedz

7

Aby uzyskać bardziej dokładne pomiary, można wypełnić TextField z łańcucha, a następnie zmierzyć szerokość tekstu, który textField użytkownika.

Kod:

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

Zastosowanie:

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 Uważasz, że musisz dodać wywołanie validateNow() po przypisaniu ciągu znaków, ale przed sprawdzeniem textWidth/textHeight przypisanie ciągu powoduje unieważnienie rozmiaru, ale ponowne obliczenie rozmiaru nie jest zsynchronizowany, więc musisz wymusić walidację – shaunhusain

+0

Świetnie! Podobało mi się rozwiązanie; Mam jednak mały problem. Nie ma odpowiedniej szerokości piksela. Dałem jej ten ciąg w tablicy. var struny: Array = ["a", "giraffe", "foo", "Obiekt ArrayCollection nie reprezentuje żadnych"]; Teraz szerokość tekstu wynosiła 245, ale w rzeczywistości rozmiar wynosił 276. Tak więc na mojej liście rozwijanej pojawi się pasek przewijania.Z twojego kodu usunąłem część, która ma textformat, więc zrobiłem funkcję measureStr funkcją argumentu 1 – Rose

+0

@Rose: TextFormat wpływa na czcionkę (-face i -family), która jest używana podczas pomiaru tekstu - powinna zostać zmieniona aby dokładnie pasować do listy rozwijanej (chociaż nie jestem pewien co to jest). Po usunięciu elementów textFormat, czy ma odpowiednią długość? Jeśli tak, podejrzewam, że tak jest, ponieważ domyślny format tekstu jest taki sam, jak używany na liście rozwijanej. – Cameron

1

nie mam edycji priv innych ludzi Post jest tak jestem delegowania to jako odrębnej odpowiedzi, ale kredyt powinien udać się do Camerona czy to działa:

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

Jeśli widzę, że tak jest, a jego treść jest edytowana, usunę ten element ze względu na czystość.

Przepraszam, że początkowo śmieciarka próbowała odpowiedzieć na pytanie właśnie tak błędnie ... w każdym razie przetestowała to i wydaje się działać. Zrobiłem to w Flex ale powinieneś być w stanie po prostu użytkowania części AS3 nie ma problemu po prostu zawinięte się pole tekstowe w UIComponent dostać go na scenie, ale stosując autoSize wydaje się działać prawidłowo:

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

, ale czy klasa textField ma metodę 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! Przepraszam, ale w tym scenariuszu użyłem metody validateNow ... prawdopodobnie masz rację, ponieważ TextField to komponent Flash, a nie Flex, schemat sprawdzania, o którym mówiłem, dotyczy komponentów Flex ... zrobiłem to z polem tekstowym, ale także, że być może będziesz musiał ustawić auto-size lub coś podobnego do tej linii ... opublikuje zmianę powyżej w kilka minut – shaunhusain

+0

Interesujące ... Jesteś pewien, że robi to "autoSize" a nie fakt, że pole tekstowe jest dodawane do sceny? – Cameron

0

Jest bardziej dopracowana wersja niektórych z powyższych kodów. Rozliczanie linebreaków (html break i \ n) i unieważnianie utworzonego obiektu Textfield z kilkoma innymi optymalizacjami. Mam nadzieję, że to jest pomocne.

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

Jeśli wolisz to w klasie, to sprawdzić w moim GIT ram: https://github.com/charlesclements/as3-tools/blob/master/net/charlesclements/util/text/TextUtil.as

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

Ponadto, nasz Flash/JS brat Jack Doyle @ GreenSock ma kilka przydatnych rzeczy do manipulowania tekstem. Warto to sprawdzić: http://www.greensock.com/splittext/

Powiązane problemy