Mobile ItemRenderer in ActionScript (Part 1)

If you are starting to do mobile development and are used to create all your ItemRenderers in MXML, you may notice that the small devices like phones and tablets do not perform as well as the desktop does and you need to start looking closely to different ways to optimize you app.


If you are starting to do mobile development and are used to create all your ItemRenderers in MXML, you may notice that the small devices like phones and tablets do not perform as well as the desktop does and you need to start looking closely to different ways to optimize you app.

One of the ways to optimize your mobile app is to create your ItemRenderers in ActionScript. Narciso Jaramillo wrote a good article for Devnet with great tips for mobile development and one of the items was exactly that, to keep your ItemRenderers in pure ActionScript.

Narciso mentions the Flex Framework comes with two ItemRenderers one is LabelItemRenderer that extends UIComponent and the other is IconItemRenderer that extends LabelItemRenderer. Those classes are great, but sometimes you have a different use case that needs a different set of classes. So in my examples I will not use those renderers. Instead, I will extend from UIComponent directly or from SpriteVisualElement for an even more lightweight class than UIComponent.

For the purpose of this tutorial, I'm planning a series of posts explaining the basics and moving on to more difficult renderers.

Basic Example

Let's start with the most simple renderer, a TextField that displays some text. To make it simple, we will extend from UIComponent and implement the IDataRenderer interface required from the List.

But before talking about the renderer, let's talk about the other elements.

Application

You need to create a Mobile project. In this example, I use the simplest of all root containers, that is an Application, not the TabbedApplication nor ViewBasedApplication subclasses. I added a List that expands 100% as the only element.

Styles

I added an external StyleSheet where I have all the styles for the ItemRenderer:

@namespace s "library://ns.adobe.com/flex/spark"; @namespace renderers "renderers.*"; renderers|UILabel { fontSize: 20; color: #000000; font-family: "_sans"; min-height: 50; padding-left: 10; }

ItemRenderer

I have a simple class extending UIComponet that gives me a few handy methods and the ability to participate in the CSS framework.

The 3 methods from UIComponent that we use are the following:

  • measure where we read the min size of the renderer from the style sheet. That comes in handy because devices with different dpi resolutions need different sizes.
  • createChildren where we create the TextField, set the styles and if there is the data already available, we set the text in the TextField to be displayed.
  • updateDisplayList where we layout the elements and we draw a line separator for each ItemRenderer.

In additions to those methods, we have the data property, which is the implementation of the IDataRenderer interface. That interface is the contract with the List and it is the way that the data is pushed to the ItemRenderer. If the TextField exists at the moment when the data is set, we set the text on the TextField, otherwise, we save it for later.

package renderers { import flash.text.Font; import flash.text.TextField; import flash.text.TextFormat; import mx.core.IDataRenderer; import mx.core.UIComponent; public class UILabel extends UIComponent implements IDataRenderer { //Protected properties protected var labelField:TextField; // Public Setters and Getters protected var _data:Object; public function set data( value:Object ):void { _data = value; // if the textfield has been created we set the text if( labelField ) { labelField.text = Font( data ).fontName; } } public function get data( ):Object { return _data; } // Contructor public function UILabel() { percentWidth = 100; } // Override Protected Methods override protected function measure():void { measuredHeight = measuredMinHeight = getStyle( "minHeight" ); } //-------------------------------------------------------------------------- override protected function createChildren():void { labelField = new TextField(); labelField.defaultTextFormat = new TextFormat( getStyle( "fontFamily" ), getStyle( "fontSize" ) ); labelField.autoSize = "left"; addChild( labelField ); // if the data is not null we set the text if( data ) labelField.text = Font( data ).fontName; } //-------------------------------------------------------------------------- override protected function updateDisplayList( unscaledWidth:Number, unscaledHeight:Number ):void { // position the field labelField.x = getStyle( "paddingLeft" ); labelField.y = (unscaledHeight - labelField.textHeight ) / 2; // we draw a separator line between each item var lineY:int = unscaledHeight -1; graphics.clear(); graphics.lineStyle( 1 ); graphics.moveTo( 0, lineY ); graphics.lineTo( unscaledWidth, lineY ); } } }

As you can see writing an ItemRenderer in ActionScript is not as difficult as it sounds.
I'm planning to show other examples in the future with multiple elements, background, states, text manipulation, multiple columns and more.

Continue reading Part 2 of this series on Item Renderers

The source is available for download.