Flex Tutorial - Image ItemRenderer

Skill

Flex Tutorial - Image ItemRenderer

Posted in:

Just the other day a commenter on our Flex tutorial about TileList Selection Indicators had a question about how to change something about the selected item. In this case it happened to be about how to change the transparency of images that are in the list. Now instead of actually handling this inside the list itself we are going to write an ItemRenderer for this, you can check out our other tutorial on ItemRenderers for more specific information on the subject. Our ItemRenderer will check to see if the data being rendered is also the selected item of the list.

Below we have a quick demonstration of this technique. You can see that we have a simple TileList with 10 images in it and initially they are all semi-transparent. Then if you select a single image it will become completely opaque revealing the full detail of my horribly compressed JPEGs. You may also notice that I have gotten rid of the selection indicator just like how we learned to in the list selection tutorial. At the same time I have set the background color to a light teal color to show that the images are actually semi-transparent. Ok play around and you can check out the source here.

Get Adobe Flash player

Custom TileList

First I built a very very simple custom TileList class to take care of the list selection indicator. To do this all you need to do is override the main function that draws this portion of the list. This function is, of course, drawSelectionIndicator. Once the function is over written I simply returned out of it without drawing any indicator at all. This results in the following class, which I named TileListEx.

package
{
  import flash.display.Sprite;
 
  import mx.controls.TileList;
  import mx.controls.listClasses.IListItemRenderer;

  public class TileListEx extends TileList
  {
    override protected function drawSelectionIndicator(indicator:Sprite,
        x:Number, y:Number, width:Number, height:Number, color:uint,
        itemRenderer:IListItemRenderer):void
    {
      return;
    }
  }
}

Main Application

Once the custom TileList class was built it was easy to get things going. The main application only had one tag in it, the TileListEx. Inside the list we set the dataProvider by hand and added an array to it. This array holds 10 objects, each with a path property pointed to an image on the server. Here is also where we set a couple minor properties on the list including the color and useRollOver - a style to tell the list to ignore rollover highlighting. This gives us the following application start.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:local="*"
   layout="vertical" verticalAlign="middle" width="475" height="400">
  <local:TileListEx id="imageList" width="100%" height="100%"
     useRollOver="false" verticalAlign="middle" backgroundColor="#46D1E1">
    <local:dataProvider>
      <mx:Array>
        <mx:Object path="ImageTileList/one.jpg" />
        <mx:Object path="ImageTileList/two.jpg" />
        <mx:Object path="ImageTileList/three.jpg" />
        <mx:Object path="ImageTileList/four.jpg" />
        <mx:Object path="ImageTileList/five.jpg" />
        <mx:Object path="ImageTileList/six.jpg" />
        <mx:Object path="ImageTileList/seven.jpg" />
        <mx:Object path="ImageTileList/eight.jpg" />
        <mx:Object path="ImageTileList/nine.jpg" />
        <mx:Object path="ImageTileList/ten.jpg" />
      </mx:Array>
    </local:dataProvider>
  </local:TileListEx>
</mx:Application>

Alababa From Aladin

Now at this point we could run the application but we wouldn't see anything that wonderful. In order to see the cool stuff we need to create our new and improved ItemRenderer - combination hooka and coffee maker, also makes chili and fries.

Image ItemRenderer

Ok so we can now build our new item renderer that will take care of image transparency. Well the first step is simply to build the ItemRenderer. I created a new Flex component named ImageRenderer based off a Box and added an image. The image's source property is bound to the path property of the data property. Giving us something like below for our first cut.

<?xml version="1.0" encoding="utf-8"?>
<mx:Box xmlns:mx="http://www.adobe.com/2006/mxml">
  <mx:Image id="img" source="{data.path}" width="200" height="150"/>
</mx:Box>

With this we can now update the list in the application to use the item renderer by setting the itemRenderer property to ImageRenderer. The new TileListEx tag now looks like the following.

<local:TileListEx id="imageList" width="100%" height="100%" useRollOver="false"
   itemRenderer="ImageRenderer"  verticalAlign="middle" backgroundColor="#46D1E1">

The final thing we need to do is add some actionscript to our ItemRenderer class. This makes the ItemRenderer look like the following - I will define the script after.

<?xml version="1.0" encoding="utf-8"?>
<mx:Box xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="{initRenderer()}">
  <mx:Script>
   <![CDATA[
     import mx.events.FlexEvent;
     import mx.controls.TileList;
     import mx.events.ListEvent;
     import mx.events.IndexChangedEvent;
     
     private var outerList:TileList;
     
     private function initRenderer():void
     {
       this.outerList = (this.parentDocument as ImageTileList).imageList;

       this.outerList.addEventListener(ListEvent.CHANGE, updateSelected);
         
       this.addEventListener(FlexEvent.DATA_CHANGE, checkSelected);
     }
     
     private function checkSelected(event:FlexEvent):void
     {
       if(this.outerList.selectedItem == this.data)
         this.img.alpha = 1;
       else
         this.img.alpha = .3;
     }
     
     private function updateSelected(event:ListEvent):void
     {
       if(event.itemRenderer == this)
         this.img.alpha = 1;
       else
         this.img.alpha = .3;
     }
   ]]>
 </mx:Script>
  <mx:Image id="img" alpha=".3" source="{data.path}" width="200" height="150"/>
</mx:Box>

Well what do we have up there? First you will notice that there is a function tied to the creation complete event. This is so we can initialize some event listeners. If we look inside the initRenderer function we see that we first set a private variable to the tile list which we get to from the outerDocument property. Next we add two event listeners, one to listen for the change event on the tile list and one for the event that is fired when the data changes in this item renderer.

Finally we get to look at the two ways we check to see if we are selected. The checkSelected function is fired when the item renderer's data changes. At this point we check the outer list to see if the selected item is equal to the data this item renderer is holding. If so we set the image alpha to 1 otherwise set it .3. The second way we check the item selected is in the event handler for the change event on the list. This will check to see if the itemRenderer property of the event is equal to this item renderer and if so it does the same stuff as the other. We also set the default alpha on the image to .3.

Well I hope this helps at least one person, the person I wrote it for :). Also feel free to check out the source and download it from here. And if anyone has any questions, concerns, or just plain complaints feel free to let us know - unless it's the last one.

Boubalou
03/20/2008 - 08:29

Hey there,

To avoid having to create the extend TileListEx, you could simply use CSS on the TileList by setting the color to transparent as follow:

TileList
{
    roll-over-color: transparent;
    selection-color: transparent;
}

Cheer :)

-Boubalou

reply

The Fattest
03/20/2008 - 09:20

Thanks for the tip. I completely forgot about that style. I am used to making a custom selection not just getting rid of it.

reply

CharmyAngeL
08/04/2008 - 01:37

hi! the CSS selection-color: transparent; doesn't work on my code it use black color as the selectionColor? need help... Cheers!

reply

Paul
08/14/2008 - 13:38

Same same comment as CharmyAngeL, I tried the transparent method and it uses black :( Meh, guess I'll just apply this demo to a DataGrid and off I go :)

reply

Transf3r
09/02/2008 - 22:52

same problem... black is rendered when using this style

reply

The Fattest
09/03/2008 - 09:23

what version of flex are you using?

reply

Ryan
09/03/2008 - 16:11

I'm using Flex 3 and I'm having the same issue; transparent comes out as black for some reason.

reply

Nick
09/18/2008 - 11:32

Hi guys, hopefully this will help all of you Flex 3 builders. Ok, so I was having the same issue and found the answer here:

http://www.meutzner.com/blog/index.cfm/2007/2/14/List-Control--Disable-Selection-ColorHighlight

In your TileList component make sure to give it an id. (id="[YOUR ID NAME]"), then add this as well:

selectionDuration="5000"
itemClick="{[YOUR ID NAME].selectedIndex=-1}"

That should get rid of any color.

Later.

reply

dimerman
02/23/2009 - 14:06

Hello there,
I see I come late for the party, but to anyone following up on these comments: how do I extrapolate this technique to multiple selections?
If I understand correctly, this takes advantage of the list being single-selection, so the item that must be rendered differently is the one just clicked. But when you have multiple selections, how would you approach this?

thanks,
Dan

reply

The Fattest
02/23/2009 - 14:21

you just need to update the item renderer function to the following.

private function checkSelected(event:FlexEvent):void
{
  if(this.outerList.selectedItem == this.data ||
     ArrayUtil.getItemIndex(this.data, this.outerList.selectedItems) != -1)
    this.img.alpha = 1;
  else
    this.img.alpha = .3;
}

private function updateSelected(event:ListEvent):void
{
  var selected:Boolean = false;
  if(this.outerList.allowMultipleSelection) {
    selected = Boolean(ArrayUtil.getItemIndex(this.data, this.outerList.selectedItems) != -1);
  } else {
    selected = Boolean(event.itemRenderer == this);
  }
  if(selected)
    this.img.alpha = 1;
  else
    this.img.alpha = .3;
}

reply

Lakshmi narayana
03/18/2009 - 07:40

<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml"
 width="338" height="450">
  <mx:Script>
 <![CDATA[
   import mx.managers.PopUpManager;
   import mx.controls.Image;
   import mx.rpc.events.ResultEvent;
   import mx.core.Application;
   import mx.events.ListEvent;
   import mx.collections.ArrayCollection;
   import mx.controls.Alert;
   
   import mx.events.ColorPickerEvent;
   import mx.core.Application;
   import events.SearchEvent;

   private var fullImage:Image;

   private var colorTrans:ColorTransform=new ColorTransform();

   public function colorSelect(evt:ColorPickerEvent):void{
     colorTrans.color=cp.selectedColor;
     Application.application.myimg.blendMode=
       BlendMode.MULTIPLY;
     Application.application.myimg.transform.colorTransform=
       colorTrans;
   }

   private function init(obj:Object=null):void{
     if(obj==null){
       //tleWnd1.title="";
       Application.application.myimg.source="";
     }else{
     //tleWnd1.title=String(obj.title).toUpperCase();
       Application.application.myimg.toolTip="Click to Move"
       Application.application.myimg.buttonMode="true"
       Application.application.myimg.useHandCursor="true"
       Application.application.myimg.source=obj.@fullImage;
       PopUpManager.addPopUp(
         Application.application.ttl1,
         this,false);
       PopUpManager.removePopUp(Application.application.ttl1);
       addChild(Application.application.ttl1.selectedItem);
     }
   }

   public function showImage(event:ListEvent):void{
     init(event.target.selectedItem);
   }

   public function showLabel(event:MouseEvent):void{
     VSApe.selectedChild=conEditform;
   }

   public function myFunc(item:Object):String{
     Alert.show('In datatip ');
     return null;
   }

   private function deleteImage():void{      
     VSApe.selectedChild=conApe;
     Application.application.myimg.source="";
   }

   private function extract():void{
     Application.application.myimg.width=resultLimit.value;
   }
 ]]>
 </mx:Script>
  <mx:Resize id="expand"
   target="{Application.application.myimg}"
   widthTo="150" heightTo="200"/>
  <mx:Resize id="contract"
   target="{Application.application.myimg}"
   widthTo="70" heightTo="60" />

  <mx:XML id="myxml" source="gallery2.xml"/>
  <mx:XMLListCollection id="xmlListColl"
   source="{myxml.image}"/>
  <mx:ViewStack id="VSApe" height="417" width="316">
 
    <mx:Canvas  id="conApe" label="ApeForm"
     width="100%" height="100%">

      <mx:Text text="Click an image to add and edit it:"/>

      <mx:TileList id="tl" dataProvider="{xmlListColl}"
       itemRenderer="CustomItemRenderer"  
       showDataTips="true" itemClick="showImage(event)"
       dataTipFunction="myFunc"
       click="showLabel(event)"
       height="356" width="271"  x="10.5" y="26"
       dragEnabled="true">
      </mx:TileList>
    </mx:Canvas>

    <mx:Canvas id="conEditform" label="editForm"
     width="100%" height="100%" borderStyle="solid">

      <mx:Form  label="EditForm" borderStyle="solid"
       width="304" height="220">
        <mx:FormItem label="Keyword(s):"
         direction="horizontal" width="265" y="10">    
          <mx:ColorPicker id="cp"
           change="colorSelect(event)" width="22"/>
          <mx:Button label="Delete" click="deleteImage()"/>
        </mx:FormItem>  

        <mx:Button label="Resize"
         click="expand.end(); expand.play();"
         width="63" x="82" y="40"/>
        <mx:Button label="contrct"
         click="contract.end(); contract.play();"
         x="164" y="40"/>
        <mx:HBox>
          <mx:Button label="Rsize" click="extract()"/>
          <mx:NumericStepper id="resultLimit"
           value="5" stepSize="5"
           minimum="5" maximum="300" />        
        </mx:HBox>
      </mx:Form>
    </mx:Canvas>
  </mx:ViewStack>
</mx:Canvas>

- Edited to clean up code formatting and drop in language tags

reply

The Fattest
03/18/2009 - 09:09

Ok I'll bite, what is this item renderer?

reply

Lakshmi
03/20/2009 - 14:27

Hi can anyone help me on this issue i need to dynamically change the image in datagrid by selecting the
particular row,i am reading the image frm xml file and
I am displaying those values in dataGrid.

reply

karthik.k
03/23/2009 - 02:28

hi lakshmi

even i have the same problem
can we give image to selected row in datagrid instead of color

i.e when row clicked image should appear if another row clicked previous clicked image should disappear

karthik.k
cse.k.karthik@gmail.com

reply

aswath
02/26/2010 - 00:51

How to Change the Style in TileList Selected Item using Flex?

My TileList Contain some text Boxes. i want to change the text color if it's selected. Please any one help me.. Thanks

reply

mohamed felata
04/04/2010 - 04:39

hi im building an image gallery using sqlite, i store the nativePath of each pic in the database. i have an array which stores the result of each query. its a global variable. i would like to use it as my dataProvider for the tileList component. but cant seem to get it working. i have to admit i dont know much bout the tileList.
thx

reply

srikanthsp
08/23/2010 - 23:37

HI,
can we change the particular image in a list using Item renderer.

the req is
a gallery with images in it as wave..(the centtal images are bit larger than the remaining)

so i am using List(flex 4) and for images using Itemrenderer but i want some images of list to be little larger than others...

pls can any one give me some idea to how to do that..

thnx in advance..

reply

Add Comment

Put code snippets inside language tags:
[language] [/language]

Examples:
[javascript] [/javascript]
[actionscript] [/actionscript]
[csharp] [/csharp]

See here for supported languages.

Javascript must be enabled to submit anonymous comments - or you can login.

Sponsors