Flex: TileList cell switching/redraw problem using an itemRenderer
While working with the TileList component I ran into a very odd issue. Images would move around while scrolling up and down. Also when I updated the dataProvider the TileList didn't display the new information. Here is an example so you can see what is going on. You can view the source the source by right-clicking and selecting "View Source".
After a lot of research, and a post on StackOverflow, I figured out what was going on. My broken example relies on a MXML completion method (init, creationComplete, etc..) to set the source of the image in the itemRenderer.
index.mxml
ImageTile_bad.mxml
TileList reuses cells inside the component. I'm not sure why, but can't keep track of where things should render and starts switching images around. I tried overridding the data method and it works, but I wanted to find a solution that doesn't require overriding a private method.
The answer is to use a setter inside the itemRenderer to assign the value to the component. Here is a snip-it of code to show you what I mean.
index.mxml
ImageTile.mxml
When TileList redraws the cell it will pass data into the img setter. This will make sure that the cell receives the correct information when it redraws. Also switching the dataProvider on the TileList works properly now. Here is a link to the working example that has available source code. Feel free to contact me if you have any questions.
After a lot of research, and a post on StackOverflow, I figured out what was going on. My broken example relies on a MXML completion method (init, creationComplete, etc..) to set the source of the image in the itemRenderer.
index.mxml
<mx:Component>
<itemRenderers:ImageTile_bad />
</mx:Component>
ImageTile_bad.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Image xmlns:mx="http://www.adobe.com/2006/mxml" initialize="init()">
<mx:Script>
<![CDATA[
/**
* This is an example of how not to use an item render in a TileList
* */
private function init() : void {
this.source = data;
this.name = data.toString().split("/").pop().split(".").shift();
}
]]>
</mx:Script>
</mx:Image>
TileList reuses cells inside the component. I'm not sure why, but can't keep track of where things should render and starts switching images around. I tried overridding the data method and it works, but I wanted to find a solution that doesn't require overriding a private method.
The answer is to use a setter inside the itemRenderer to assign the value to the component. Here is a snip-it of code to show you what I mean.
index.mxml
<mx:Component>
<itemRenderers:ImageTile img="{data}"/>
</mx:Component>
ImageTile.mxml
<mx:Image xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
/**
* This is an example of how to use an itemRenderer in a TileList
* Create a setter that will always update the when the TileList redraws
* */
public function set img(value:String) : void {
//make sure there is something to work with. avoid error# 1010
if(!value) {
return;
}
this.source = value;
this.name = value.toString().split("/").pop().split(".").shift();
}
]]>
</mx:Script>
</mx:Image>
When TileList redraws the cell it will pass data into the img setter. This will make sure that the cell receives the correct information when it redraws. Also switching the dataProvider on the TileList works properly now. Here is a link to the working example that has available source code. Feel free to contact me if you have any questions.
Labels: creationComplete, data, dataprovider, duplicate, flex, init, itemrenderer, override, random, redraw, refresh, repeat, switch, tilelist


2 Comments:
Priceless!
I spent a few hours trying to figure out why my tilelist wasn't updating properly. By using your technique my problem is solved. I was using a Drop-In itemRender would was inconsistently updating. Wouldn't this be considered a bug in the SDK?
Thanks.
It sure feels like a bug. I spent way to much time trying to figure this out(2wk+). You really don't want to see my interim solutions. I'm glad it helped you.
In another project I was adding a canvas to the tile which was created as a canvas. When I updated the tile I had to use removeAll() on the tile before adding anything else to it. Not sure if it's a bug, or if the tileList is supposed to be used for really simple things and it falls apart when trying advanced things. It might be a side affect of object recycling to keep memory low.
Post a Comment
If you found this page useful, or you have any feedback, please leave a comment.
Links to this post:
Create a Link
<< Home