September 10th, 2007 by Kyle
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>
<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.





October 19th, 2007 at 6:51 am
I really like this example and would like to include the basic algorithm in the Flex 3 Cookbook which I’m currently working on. If you wouldn’t mind dropping me a line I’d like to get a little more info on you so I can give you credit in the book. Thanks,
October 23rd, 2007 at 9:35 am
Josh, no problem on adding the code or variation to the Flexcookbook. for a blurb on me, perhaps check out the blurb from my dev center article: http://www.adobe.com/devnet/flex/articles/helloworld.html