Grio helped to develop many aspects of the platform for this MMO - initial reviews point to LOL becoming a huge success.
« September 2009 | Main | November 2009 »
Grio helped to develop many aspects of the platform for this MMO - initial reviews point to LOL becoming a huge success.
Posted at 09:58 AM in News | Permalink | Comments (0) | TrackBack (0)
I am currently working on a project where we have a fixed-width dialog box, and need to fit the title text in a label. The problem is, the text is too long. What to do? Well, the basic Flex Label provides you a couple of options: show an ellipsis (…) at the end of the label or cut the text off. Neither of these solutions was viable.
This is a common problem that occurs in UI development: fitting text in a limited space. My solution to this was to create a LabelUtil class that automatically adjusts the font size of the text to fit the width of the label.
Here is the meat of the code:
import
flash.text.AntiAliasType;
import
flash.text.Font;
import
flash.text.GridFitType;
import
flash.text.TextLineMetrics;
import
mx.controls.Label;
import
mx.core.Application;
import
mx.core.UITextFormat;
import
mx.styles.CSSStyleDeclaration;
import
mx.styles.StyleManager;
public class LabelUtil
{
public function LabelUtil()
{
}
static public function constrainTextToWidth( label : Label, htmlText : String ) : void
{
var style : CSSStyleDeclaration =
StyleManager.getStyleDeclaration("." +
label.styleName);
var fontSize : Number = style.getStyle( "fontSize" ) as Number;
label.setStyle( "fontSize", fontSize );
label.htmlText = htmlText;
label.invalidateSize();
label.validateNow();
while (
getTextWidth( label.text, fontSize, style ) > label.width )
{
fontSize =
fontSize - 0.5;
label.setStyle(
"fontSize", fontSize );
}
}
static public function getTextWidth( text : String, fontSize
: Number, style : CSSStyleDeclaration ) : Number
{
var textFormat
: UITextFormat =
new
UITextFormat(
Application.application.systemManager,
style.getStyle(
"fontFamily" ),
fontSize,
null,
style.getStyle(
"fontWeight" ) == "bold",
style.getStyle(
"fontStyle" ) == "italic",
null,
null,
null,
null,
style.getStyle(
"paddingLeft" ),
style.getStyle(
"paddingRight" ),
style.getStyle(
"textIndent" ) );
textFormat.antiAliasType
= flash.text.AntiAliasType.ADVANCED;
textFormat.gridFitType
= flash.text.GridFitType.PIXEL;
var textMetrics
: TextLineMetrics = textFormat.measureText( text );
return
textMetrics.width;
}
}
OK, so what’s going on here? First we pass in the label in question and the html text to be displayed (note the function will also work for plain text). Then, we measure the width of the text and compare it to the width of the label. If the text is narrower that the label, we’re done. Otherwise, we reduce the font size by a half-point until the text width is less than the label width.
There are a couple of things to consider using this method: First, you must specify the width of your label in pixels (this shouldn’t be a problem as this solution applies to a fixed width label). Also, you’ll need to make sure to define a CSS style for the label (you could modify the method to use the label’s inherent style properties, but I didn’t need to).
Notice that I am using a UITextFormat object to measure the text width. Why is that, when the label provides a textWidth property? The answer is that textWidth is unreliable in the label control. This method is rock solid.
Hope this helps your labeling needs. Happy Coding!
Posted at 01:45 PM in AIR/FLex | Permalink | Comments (1) | TrackBack (0)
We've been busily developing using Flex 4 (aka “Gumbo”) here at the Grio offices and are impressed with many of its new features. One of the more interesting but difficult to decipher features is the TextFlow component.
The TextFlow component is used to layout text in a highly controlled way. It uses an XML-based markup language, Text Layout Format (TLF), to define the content of the TextFlow. TLF uses some similar tags to HTML (<div>, <p>, <span>), but it is definitely not HTML. This may trip you up a bit as you learn TLF; I recommend reading the Adobe Labs info before diving too deep into development (http://labs.adobe.com/technologies/textlayout/).
Adobe Labs also provides a nice text editor that can read and write TLF (http://labs.adobe.com/technologies/textlayout/demos/ ; a note of caution: the editor is somewhat out of date, so the TLF generated may not work perfectly with the latest text layout package).
One important thing to note is that The HTML to TLF conversion capabilities built into the Text Layout package are crap. They do not support much of anything, except paragraphs. Lists are not supported, and CSS is not either. For our last project, we basically built our own translator to generate TLF from HTML.
Which leads me to reveal my trick to render bulleted lists in TLF. The keys are: 1) The Unicode bullet character (\u2022); 2) A negative paragraph textIndent format attribute; and 3) The paragraphStartIndent attribute.
Here’s the format definition for each list item:
<format id='list_item' paragraphStartIndent='15' textIndent='-9' paragraphSpaceAfter='10'/>
Note that we have a negative textIndent and a positive paragraphStartIndent. This gives the desired list effect. You will need to adjust these numbers based on the size and face of the font you are using.
And here’s the function that converts the HTML list to a TLF list:
private static function appendList(htmlListNode:XML, tlfXml:XML, isOrdered:Boolean):void {
//used for ordered lists
var count:int = 1;
var listEl : String = isOrdered ? "ol" : "ul";
//get the li tags
for each (var child:XML in htmlListNode.*) {
var lineItemXml:XML;
var listItemContent:String = child.children().toXMLString();
// Ensure content for list item
if (listItemContent.length == 0) continue;
listItemContent = listItemContent.toLowerCase();
listItemContent = listItemContent.replace("<strong>","<span fontWeight='bold'>");
listItemContent = listItemContent.replace("</strong>","</span>");
if (listItemContent.indexOf("<ul>") > -1) {var preNestedListText:String = listItemContent.substring(0,listItemContent.indexOf(listEl));
var nestedList:String = listItemContent.substring(listItemContent.indexOf(listEl), listItemContent.length);
var nestedListXml:XML = new XML(nestedList);
if(preNestedListText.length > 0) {if(isOrdered) {
tlfXml.appendChild(new XML("<p listitem='true' format='list_item'>" + count + ". " + listItemContent +"</p>"));
} else {
tlfXml.appendChild(new XML("<p listitem='true' format='list_item'>\u2022 " + listItemContent + "</p>"));
}
}
appendList(nestedListXml, tlfXml, false);} else {
if(isOrdered) {
tlfXml.appendChild(new XML("<p listitem='true' format='list_item'>" + count + ". " + listItemContent +"</p>"));
} else {
tlfXml.appendChild(new XML("<p listitem='true' format='list_item'>\u2022 " + listItemContent + "</p>"));
}
count++;}
}
}
In summary, TLF is a very powerful text formatting language, but it currently lacks good HTML conversion tools and simple tags for things such as lists. We hope Adobe provides support for these in the future, but until then we’ll just have to code around the problem.
Posted at 02:14 PM in AIR/FLex | Permalink | Comments (4) | TrackBack (0)
Grio developed the vook platform and Flex-based reader. Look for new vooks to come out on a regular basis.
Posted at 10:03 AM in News | Permalink | Comments (0) | TrackBack (0)