Flex 4 and the Text Layout Framework

April 26, 2010By 22 Comments

One of my favorite things about Flex 4 is that it now includes the Text Layout Framework (TLF) as the basis of many Spark text components such as RichText, RichEditableText, TextArea, and TextInput as well as any other components that utilize any of these as part of another component, such as the ComboBox, which includes a TextInput control for example. You now have fine-grained control over text and text flow and can do some really amazing things with your UIs. This framework is extensive and I recently took some time to go through it all while building samples for Tour de Flex. I’d like to share some information I gathered while doing so.

The Text Layout Framework is included in Flex 4 via the textLayout.swc. This swc contains three combined SWC’s including:
• textLayout_core
• textLayout_conversion
• textLayout_edit

The textLayout_core component is the main component for the framework and handles storage and display of text.
The textLayout_conversion component is used for import/export of text and is necessary if you use text that is not compiled directly into the SWF.
The textLayout_edit component provides the editing libraries needed for selection, editing (cut/copy/paste) and undo capabilities.

This framework can be understood better when looking at it from an MVC standpoint. The packages that make up each part are listed below:

Model

  • flashx.textLayout.elements.* (classes for data structure definition)
  • flashx.textLayout.formats.* (classes for formatting properties)
  • flashx.textLayout.conversion.* (classes for import/export)

View

  • flashx.textLayout.factory.*
  • flashx.textLayout.container.*
  • flashx.textLayout.compose.*

Controller

  • flashx.textLayout.edit.*
  • flashx.textLayout.operations.*

Importing Text
In many cases you will need to import text into the framework. This can be especially useful for importing dynamic text that is returned from a remote service or HTTPService at runtime for instance. You can choose from three different conversion options for import/export of text in general. They are:

TextConverter.TEXT_LAYOUT_FORMAT – convert to/from the text layout markup format
TextConverter.PLAIN_TEXT_FORMAT – convert to/from a plain text string
TextConverter.TEXT_FIELD_HTML_FORMAT – convert to/from HTML (subset of HTML supported – see here for details)

The following example shows how to use the TLF markup language itself within some text and then import it into the framework for managing the display:

private static const textInput:XML = <TextFlow xmlns="http://ns.adobe.com/textLayout/2008">
	<div>
	<p color="0x336699"><span>The Text Layout Framework is an extensible library, built on the new text engine in Adobe Flash Player 10, which delivers advanced, easy-to-integrate typographic and text layout features for rich, sophisticated and innovative typography on the web.
	</span></p>
	</div>
	</TextFlow>;

private var _textFlow:TextFlow;
var importer:ITextImporter = TextConverter.getImporter(TextConverter.TEXT_LAYOUT_FORMAT);
textFlow = importer.importToFlow(textInput);

You could also do something like the following with plain text. Note that this example specifies the format directly on the import method, whereas the code above retrieved an import filter first with a call to getImporter(). If you want to catch errors on the conversion then you would use the one that gets the import filter first such as above.

private static var myText:String = "Hello World";
private var _textFlow:TextFlow;
textFlow = importer.importToFlow(myText,TextConverter.PLAIN_TEXT_FORMAT);

You can export your text to those same formats. An example of exporting text to the Text Layout Framework markup is shown here:

TextConverter.export(customEditor.editor.textFlow,
TextConverter.TEXT_LAYOUT_FORMAT,
 ConversionType.STRING_TYPE);

Applying this to Flex 4 controls, you could use any of the TLF-based controls’ textFlow property and set that value to the imported String result. The following code snippet shows how this is done:

	<fx:Declarations>
		<!-- Define a String to use with HTML and plain text format. -->
		<fx:String id="htmlTxt"><![CDATA[<p>Text containing <b>HTML</b> markup</p>]]></fx:String>

		<!-- Define an XML object to use with TLF format. -->
		<fx:XML id="tfTxt">
			<TextFlow xmlns="http://ns.adobe.com/textLayout/2008">
				<p>Text Using  <span fontWeight="bold">Text Layout Framework</span> Markup</p>
			</TextFlow>
		</fx:XML>
	</fx:Declarations>
	<s:TextArea id="txt1" width="200" height="50"
						textFlow="{TextConverter.importToFlow(htmlText, TextConverter.TEXT_FIELD_HTML_FORMAT)}"
						horizontalCenter="0" verticalCenter="0" />
	<s:RichText id="txt3" width="200" height="50"
						textFlow="{TextConverter.importToFlow(tfText, TextConverter.TEXT_LAYOUT_FORMAT)}"
						horizontalCenter="0" verticalCenter="0" />

You can also use the TextFlowUtil class to import a String into a Flex 4 TLF-based component as in the following code snippet:

		var markup:String = "<TextFlow xmlns='http://ns.adobe.com/textLayout/2008'><p fontFamily='Arial'>This is TLF markup with paragraphs.</p><p color='0x663399'>The root TextFlow tag is included.</p></TextFlow>";
		rt1.textFlow = TextFlowUtil.importFromString(markup);

		<s:TextArea id="rt1" width="300" height="50"/>

Note that you can even omit the TextFlow root and namespace and simply start with the paragraph tag and the TextFlow root and namespace will be added for you; for example:

		var markup:String = "<p color='0xCE267D'>This is TLF markup with paragraphs.</p><p fontSize='10' fontWeight='bold' fontFamily='Arial'>The root TextFlow tag is omitted and therefore created automatically.</p>";
		rt1.textFlow = TextFlowUtil.importFromString(markup);

                <s:RichText id="rt1" width="200"/>

There are some important classes that are key to the framework:

TextFlow
Represents the text itself and can contain either ParagraphElement (p) or DivElement (div). DivElement can be a group of ParagraphElements. ParagraphElement (p) can contain span, inline image, link or tcy elements (for Japanese text handling). The following picture is from the Adobe SDK docs and helps explain the relationship hierarchy further:

The TextFlow can contain multiple containers and each container is associated with a ContainerController.

ContainerController
A controller is associated with each container that is being used to display text (manages a Sprite for instance). The controller is used to control how the text is going to flow between containers. Here is another image from the Flex 4 SDK docs that I believe helps explain this nicely:

IFlowComposer
The IFlowComposer interface is implemented by the StandardFlowComposer and manages the conversion of the text into TextLine objects and placement of the text in the containers. The updateAllControllers() net must be called on this object to lay out the text and add update the display when any settings have been changed.

For instance:

textFlow.fontSize = 11;
flow.flowComposer = new StandardFlowComposer();
textFlow.flowComposer.updateAllControllers();

TextLayoutFormat
Formatting of text can be done in multiple ways, either at the container, paragraph, or character level. It’s done by using either a TextLayoutFormat object, which contains all of the properties that can be set, or by setting the specific properties on the TextFlow object. If you use the TextLayoutFormat object, you then assign it to the format property of the TextFlow object:

var tlf:TextLayoutFormat = new TextLayoutFormat();
tlf.fontSize =11;
tlf.direction = Direction.RTL;
tlf.columnCount = 3;
tlf.columnGap = 15;
textFlow.format = tlf;

If you are only changing one attribute, you can do so on the TextFlow object directly as well:

textFlow.fontSize = 11;

The following sample code snippets show some specific techniques you might want to use with this framework:

Directional Text

textFlow.direction = Direction.RTL; // right-to-left text

Inline Images
You can display an inline image in your text with something like the following:

[Embed(source="adobe_air_logo.png")]
[Bindable]
static public var imgClass:Class;

var p:ParagraphElement = new ParagraphElement();
var inlineGraphicElement:InlineGraphicElement = new InlineGraphicElement();
inlineGraphicElement.source = imgClass;
inlineGraphicElement.width=32;
inlineGraphicElement.height=32;
p.addChild(inlineGraphicElement);
textFlow.addChild(p);

Selecting/Editing Text
You can create an EditManager with an UndoManager if you would like to use selection, editing, and undo capabilities. If you only need to support selection, you can use the base SelectionManager class. Below is code that shows how to set up the code to handle editing/undo. See the FlowOperation class docs for more information on the types of operations that can be handled. The new Tour de Flex sample shows how to do selection, undo, and redo of text so check that out for more information.

textFlow.interactionManager = new EditManager(new UndoManager());

A great example of the Text Layout Framework in use is the New York Times Adobe AIR application. If you haven’t downloaded this app yet, I highly recommend it, and it’s FREE!

And finally some links for further information:
Tour de Flex TLF Samples
Text Layout Framework Team Blog – great examples here too!
InsideRIA article by Elad Elrom on MXML and TLF
Text Layout Frameworks on Adobe Labs
Try out TLF with an online editor

Filed in: FlashFlex 4Flex/AIR Tags:

About the Author ()

Comments (22)

Trackback URL | Comments RSS Feed

Sites That Link to this Post

  1. How To: Find .NET3 and .NET3.5 versions | April 27, 2010
  1. Pradeek says:

    Hi, can you give any info on working with dynamic HTML formatted text using TLF? I can’t seem to find much about it.

    • calvin says:

      It doesnt work well, I have errors when using b or strong for example any small issues and it fails, not a great solution this really is Beta for me and should not be released.

  2. JTtheGeek says:

    Awesome write up on the TLF! I wish this had been around when I was getting started with it. I can’t thank Adobe for adding this into the flash engine, it has been amazingly powerful for working with text in a document processor app I’ve been putting together. Being able to know exactly where characters are on the screen alone is worth gold. Keep up the great work.

  3. Julia says:

    Invaluable stuff! So thrilled there is better text controls! It was the one area that was seriously hampering our apps!!

  4. daslicht says:

    Hi,

    is there a way to add a EventListener to a inline Graphic Element?

    How?

  5. daslicht says:

    Hi,

    is there a way to add an EventListener to an InlineGraphicElement?

    How? Any help is welcome.

  6. Peter Sahajian says:

    Hey devGirl/Holly, I’ve got a problem I’m running into; it’s a simple and common AS3 mistake, but I find that none of the other solutions help. I’m hoping that it’s something I missed about your very good description.

    I am trying to utilize your tutorial on using the TLF markup language within some text and then importing it into the framework for managing the display, via your first block of code above.

    I declare the private static const textInput XML file as you did, and hardcode in the TLF markup language. I then declare a private var textFlow of type TextFlow, as well as a variable importer, exactly as you did. Finally, I attempt to set “textFlow = importer.importToFlow(textInput);
    “, but I keep getting Error1120′s about the access of undefined property _textFlow and access of undefined property “importer” despite the fact that they are DECLARED right above it! For some reason, the code won’t work because it doesn’t know where to find the declared vars _textFlow and importer, despite them being declared in the previous lines…

  7. Wow says:

    I’m thinking can i input in Chinese in AIR?
    the old versions cannot input anything in Chinese in Air….

  8. Jeannie says:

    I am using your very helpful information about •flashx.textLayout.conversion.* (classes for import/export) My client wishes to keep the text external for SEO and updateable reasons. I am seeking well-explained documentation on using TLF that keeps extermal xml text files from being embedded.

    Using: <fx:XML id="textFlowAsXML" source="cleaning.xml" in my declarations tag, displays perfectly, but the xml text content gets embedded into the swf.

    Using the following I have no errors but not text displays either:

    In the script block, I have:

    protected function getContentFromXML_result(event:ResultEvent):void {
    var res:XML=event.result as XML;

    var masterTf:TextFlow=new TextFlow;
    //masterTf=TextFlowUtil.importFromXML(res, WhiteSpaceCollapse.COLLAPSE) ;

    var homeTf:TextFlow=new TextFlow;
    homeTf.addChild(masterTf.getElementByID(“home”));
    home_Ta.textDisplay.textFlow=homeTf;
    var tlf_hover:TextLayoutFormat = new TextLayoutFormat();
    tlf_hover.color = 0xfbee23;
    var tlf_link:TextLayoutFormat = new TextLayoutFormat();
    tlf_link.color = 0x69e778;

    homeTf.linkHoverFormat=tlf_hover;
    homeTf.linkNormalFormat=tlf_link ;
    }
    protected function getContentFromXML_fault(event:FaultEvent):void {
    Alert.show(“Could not reach server./n”+event.fault.message);
    }

    Would you kindly direct me to a full source file? Or might you be available for hire to help me?

    Jeannie

  9. JackKarter says:

    Hi,is there a way to add an EventListener to an InlineGraphicElement? Thanks in advance.

  10. john says:

    Thank you.

  11. Tom says:

    What about performance ? I know Adobe Flash got angry about this … but I am afraid if the TLF creates a new object for EACH XML nodes .. it will be a nightmare for users battery ;-) (as usually with Flash …)

  12. Waseem says:

    Hi,
    can anyone help me regarding i want to create text layout like in Times Reader Application (i.e. i want to split my text in multiple columns and multiple pages). Kindly help me out or provide me with some sample code.

  13. tabman says:

    How can Arabic be specified as input text ?

  14. Nathan5x says:

    Hi Holly …

    Nice to see your very detailed post on TLF. It has a lot in it.

    Could you please share the difference between TextLayoutFormat and TextFormat ?

    And when to use these two ?

  15. Zar Chi says:

    Hi Holly…

    I’ve been trying to style the textflow using the stylesheet and couldn’t manage to do that. I’ve been trying like 2 days now. I also tried with CSSFormatResolver and nothing happened and still don’t understand how it’s gonna work. Is there any other way to style the textflow using stylesheet?

    thanks

  16. Hardik says:

    Hi DevGirl

    TLF:-

    Plz Help me…
    How to Resize Font Size as per Component Size….
    mean auto adjust font in Component …

  17. Andrei says:

    It looks like I have a problem whit the TextInput/TextArea. In my mobile application they don’t allow me to type text, I’ve tried in both full screen and screen mode, I’ve changed the to “cpu” in the myApp-app.xml and nothing! If anybody knows how to fix this, please help!

    Thank You!

  18. Kaleel says:

    Hi

    I am new to Flex,

    I trying to display HTML formatted Tamil Rss Feed in RichEditableText

    Font is not rendering properly , i breaking my head for the past 2 weeks.

    Code below

    Plz HElp.

  19. Than says:

    Hi,

    I found this post while looking for a way to write a fraction (numerator/denominator) using TLF. Any help would be really valuable!

  20. hamed says:

    I have the problem using tlf in mobile applications. I develooed a flex mobile apps for android that doesnt display arapic/persian text . All labels and buttons refuse to display text properly . Plz help

Leave a Reply