Our Blog

This is part 5 of my series on item renderers. As you may know, the Mobile Flex Framework does not have a DataGrid, mostly because a DataGrid control uses a lot of real state and the phone has a small screen. But, we have tablets too and a Grid makes complete sense. However, the regular flex DataGrid will not work as it is too heavy for that. We also want gestures and bouncing like the mobile List has. So the workaround is to make an ItemRenderer that mimics a grid.

Grid Renderer

For this example I'm reusing the code of the Application from the previous Twitter example so I will not explain that. Also I'm reusing some of the pieces from the TweetRenderer but changing the layout a lot.

For reference, these are the previous posts: part 1, part 2, part 3 and part 4.

Styles

The main difference from the previous example is that I don't have individual styles for each TextField. Instead, all the fields use the same one. The new thing that I added is the vertical-grid-line-color property used to paint the vertical lines. renderers|TweetGridRenderer

renderers|TweetGridRenderer
{
   padding-left: 15;
   padding-right: 15;
   gap: 20;
   
   min-height: 50;
   vertical-grid-line-color:#aaaaaa;
   font-size: 15;
   color: #555555;
   font-family: _sans;
   separator: Embed(source='/styles/images/separator.png' );
   
   background: Embed(source='/styles/images/background_up.png',
      scaleGridLeft=10, scaleGridTop=20, scaleGridRight=11, scaleGridBottom=21 );
}

renderers|TweetGridRenderer:selected
{
   background: Embed(source='/styles/images/background_down.png',
      scaleGridLeft=50, scaleGridTop=20, scaleGridRight=51, scaleGridBottom=21 );
}

TweetGridRenderer

This class has some similar elements to the TweetRenderer. The main differences are:

  • I added a lineCanvas display object used to paint the vertical lines.
  • I use fix height instead of variable height. The height is set by reading the value from the CSS.
  • I use the same styles for all the fields. Note that we do that when we call TextUtil.createSimpleTextField and pass "this".
  • I changed the layout off all the fields and removed the avatar image.
package renderers
{
   import flash.display.DisplayObject;
   import flash.display.Graphics;
   import flash.display.Shape;
   import flash.text.TextField;
   import utils.TextUtil;
   public class TweetGridRenderer extends BaseRenderer
   {
      protected var userField:TextField;
      protected var nameField:TextField;
      protected var contentField:TextField;
      protected var background:DisplayObject;
      protected var backgroundClass:Class;
      protected var separator:DisplayObject;
      protected var lineCanvas:Shape;
      protected var columnWidth:int
      protected var paddingLeft:int;
      protected var paddingRight:int;
      protected var paddingBottom:int;
      protected var paddingTop:int;
      protected var gap:int;
      
      // Contructor
      public function TweetGridRenderer()
      {
         percentWidth = 100;
      }
      
      // Override Protected Methods
      override protected function createChildren():void
      {
         readStyles();
         setBackground();
         var separatorAsset:Class = getStyle( "separator" );
         if( separatorAsset )
         {
            separator = new separatorAsset();
            addChild( separator );
         }
         userField = TextUtil.createSimpleTextField( this );
         addChild( userField );
         nameField = TextUtil.createSimpleTextField( this )
         addChild( nameField );
         contentField = TextUtil.createSimpleTextField( this );
         addChild( contentField );
         lineCanvas = new Shape();
         addChild( lineCanvas );
         // if the data is not null, set the text
         if( data )
            setValues();
      }
      override protected function updateDisplayList( unscaledWidth:Number, unscaledHeight:Number ):void
      {
         var oldColumnWidth:int = columnWidth;
         columnWidth = Math.floor( unscaledWidth / 3 );
         if( columnWidth != oldColumnWidth )
            setValues();
         var textWidth:int = columnWidth - paddingLeft - paddingRight;
         background.width = unscaledWidth;
         background.height = unscaledHeight;
         var textY:int = ( unscaledHeight - userField.textHeight ) / 2;
         userField.x = paddingLeft;
         userField.y = textY;
         TextUtil.adjustTextSize( userField, textWidth );
         nameField.x = columnWidth + paddingLeft;
         nameField.y = textY;
         TextUtil.adjustTextSize( nameField, textWidth );
         contentField.x = columnWidth * 2 + paddingLeft;
         contentField.y = textY;
         TextUtil.adjustTextSize( contentField, textWidth );
         separator.width = unscaledWidth;
         separator.y = layoutHeight - separator.height;
         var g:Graphics = lineCanvas.graphics;
         g.clear();
         g.lineStyle( 1, getStyle( "verticalGridLineColor" ) );
         g.moveTo( columnWidth, 0 );
         g.lineTo( columnWidth, unscaledHeight );
         g.moveTo( columnWidth * 2, 0 );
         g.lineTo( columnWidth * 2, unscaledHeight );
      }
      override protected function measure():void
      {
         measuredHeight = getStyle( "minHeight" );
      }
      protected function setBackground():void
      {
         var backgroundAsset:Class = getStyle( "background" );
         if( backgroundAsset && backgroundClass != backgroundAsset )
         {
            if( background && contains( background ) )
               removeChild( background );   
            backgroundClass = backgroundAsset;
            background = new backgroundAsset();
            addChildAt( background, 0 );
            if( layoutHeight && layoutWidth )
            {
               background.width = layoutWidth;
               background.height = layoutHeight;
            }
         }
      }
      override protected function setValues():void
      {
         var arr:Array = String( data.author.name ).split("(");
         var user:String = String( data.author.name )
         userField.text = arr[0];
         nameField.text = String( arr[ 1 ] ).replace( ")", "" );
         contentField.htmlText = data.content.value;
      }
      override protected function updateSkin():void
      {
         currentCSSState = ( selected ) ? "selected" : "up";
         setBackground();
      }
      protected function readStyles():void
      {
         paddingLeft = getStyle( "paddingLeft" );
         paddingRight = getStyle( "paddingRight" );
         gap = getStyle( "gap" );
      }
   }
}

As you can see this renderer is very similar to the one on our previous example. By making just some adjustments we have a completely new layout. Hope you enjoyed this series on item Renderers.

The source is available for download.

Nahuel Foronda

Nahuel Foronda

5 Comments

  1. mikimi

    mikimi

    Hi,
    i'm trying to set the HtmlText property with no success to show different colors for the words in a single TextField with no success.why?
  2. mihai
    when i use 2 o these grids in an app, the background on the second grid remains null and crashes when trying to set it's width
  3. mihai
    figured it out...i'm such a noob, i was having my css point to just one of the grids, moved it to base render and it's all fine now
  4. karunakar

    karunakar

    pls send cairngorm example with clear notes