September 10th, 2007 by Kyle
Tags: arraycollection, Flex, idropinlistitemrenderer, itemrenderer, tilelist, toggle, toggle-buttons, togglebutton, uuid
Posted in: Flex
I had a customer ask how they could use a button itemRenderer in a tile list, have the buttons toggle, and keep track of all the toggled buttons so one could easily clear all the toggled buttons. Here is what I came up with:
The key to this is that if your TileList has a dataprovider that is an array collection, within an itemRenderer, each item’s BaseListData will have a UUID.
If you extend the Tilelist and add a public member that is an arrayCollection that is used to contain all the UUIDs of toggled buttons, then management of those toggled buttons become quite easy.
Here is my simple extension to TileList:
<mx:TileList xmlns:mx="http://www.adobe.com/2006/mxml"
initialize="acToggledButtons = new ArrayCollection()">
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
public var acToggledButtons:ArrayCollection;
public function removeAll():void{
acToggledButtons.removeAll();
this.invalidateList();
}
]]>
</mx:Script>
</mx:TileList>
Here is the itemRenderer:
<mx:Script>
<![CDATA[
import mx.controls.listClasses.BaseListData;
import mx.controls.Button;
import mx.controls.TileList;
import MyTileList
private var _listData:BaseListData;
[Bindable]
public var key:String;
private var myTL:MyTileList;
public function get listData():BaseListData {
return _listData;
}
public function set listData( value:BaseListData ):void {
_listData = value;
myTL = _listData.owner as MyTileList;
key=_listData.uid;
}
private function onChange(event:Event):void{
var i:int=myTL.acToggledButtons.getItemIndex(key);
if(i>=0 && (event.target as Button).selected==false){
myTL.acToggledButtons.removeItemAt(i);
}
else if(i==-1 && (event.target as Button).selected==true){
myTL.acToggledButtons.addItem(key)
}
myTL.invalidateList();
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void{
super.updateDisplayList(unscaledWidth, unscaledHeight);
if(key){
var i:int=myTL.acToggledButtons.getItemIndex(key);
if(i>=0){
btn.selected=true;
}
else{
btn.selected=false;
}
}
}
]]>
</mx:Script>
<mx:Button id="btn" width="100%" label="{data.Label}" toggle="true" change="onChange(event)"/>
</mx:VBox>
Here is an app using this TileList and itemRenderer:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="*"
layout="vertical" creationComplete="callLater(doStuff)">
<mx:Panel id="buju" backgroundColor="#b7babc" borderStyle="none" horizontalAlign="center" width="100%"
title="toggle buttons" creationComplete="comp()" >
<MyTileList id="tile" width="100%" height="100%"
dataProvider="{dp}" itemRenderer="MyRenderer"
verticalScrollPolicy="off" visible="false" />
<mx:ControlBar>
<mx:Button label="select none" click="selectNone()" />
</mx:ControlBar>
</mx:Panel>
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable] private var dp:ArrayCollection = new ArrayCollection();
private function comp():void{
for(var i:int = 0; i < Math.round(Math.random()*150)+10 ; i++){
var tmp:Object = new Object();
tmp.Label = "number: "+i;
dp.addItem(tmp);
}
tile.columnCount = Math.floor(Math.sqrt(dp.length));
}
private function doStuff():void{
tile.height=tile.rowHeight*Math.ceil(tile.dataProvider.length/tile.columnCount)+tile.getStyle("borderThickness")*2;
callLater(function foo():void{tile.visible=true;});
}
private function selectNone():void{
tile.removeAll();
}
]]>
</mx:Script>
</mx:Application>
Here is a link to a Flex Builder 2.0.1 project (compiled with SDK hotfix2) containing a sample demonstrating the solution described above.

