Going with the Flow: Tips and Tricks for Using the Adobe Flex TextFlow Component
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( tyle=”color: #990000; font-size: 11px;”>“</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 + “. “ n style=”font-family: Courier;”> + 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.
2 Comments