Custom Component - SortableTileList
Posted by Fedele Marotti under ActionScript 3, Components, Flex
This example shows you how to create a component that extends the TileList and gives you the possibility to sort the element;
This movie requires Flash Player 9
The Application:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="{init()}"
layout="absolute" xmlns:creativesource="it.creativesource.*">
<mx:Script>
<![CDATA[
import it.creativesource.SortObject;
import it.creativesource.DisplayItem;
import mx.collections.ArrayCollection;
[Bindable]
private var dp:ArrayCollection=new ArrayCollection();
[Bindable]
private var fields:ArrayCollection=new ArrayCollection();
private function init():void{
var field1:SortObject=new SortObject("field1");
var field2:SortObject=new SortObject("field2");
var field3:SortObject=new SortObject("field3");
field1.label="Sort by field1";
field2.label="Sort by field2";
field3.label="Sort by field3";
field1.isNumeric=true;
field2.isNumeric=true;
field3.isNumeric=true;
fields.addItem(field1);
fields.addItem(field2);
fields.addItem(field3);
for(var i:int=0;i<10;i++){
var obj:Object={};
obj['field1']=i;
obj['field2']=Math.round(Math.random()*100);
obj['field3']=Math.round(Math.random()*100);
dp.addItem(obj);
}
}
]]>
</mx:Script>
<creativesource:SortableTileList
itemRenderer="it.creativesource.DisplayItem"
dataProvider="{dp}"
x="10" y="10"
width="400" height="480"
sortableFields="{fields}"
/>
<mx:Button x="418" y="10" label="Button"/>
<mx:Button x="418" y="468" label="Button"/>
</mx:Application>
The SortableTileList.as:
package it.creativesource
{
import flash.events.MouseEvent;
import mx.collections.ArrayCollection;
import mx.collections.ICollectionView;
import mx.collections.Sort;
import mx.collections.SortField;
import mx.controls.TileList;
import mx.events.CollectionEvent;
public class SortableTileList extends TileList
{
[Bindable]
private var _header:ArrayCollection=new ArrayCollection();
[Bindable]
private var _fields:ICollectionView=new ArrayCollection();
private var _currentSort:Sort=new Sort();
public function SortableTileList(){
super();
_fields.enableAutoUpdate();
}
override protected function createChildren():void{
super.createChildren();
this.y+=22;
this.height-=22;
}
public function set sortableFields(fields:ArrayCollection):void{
_header=new ArrayCollection();
_fields=fields
if(!_fields.hasEventListener(CollectionEvent.COLLECTION_CHANGE))
_fields.addEventListener(CollectionEvent.COLLECTION_CHANGE,createBtn);
}
private function createBtn(e:CollectionEvent=null):void{
for(var i:int=0;i<_header.length;i++){
try{
removeChild(_header.getItemAt(i) as SortBtn);
}catch(e:*){}
}
_header=new ArrayCollection()
for(i=0;i<_fields.length;i++){
if(!(_fields[i] is SortObject)){
throw new Error("Fields must be SortObject");
}
var b:SortBtn=new SortBtn();
b.label=_fields[i].label;
b.field=_fields[i].field;
b.styleName="SortBtn";
b.isNumeric=_fields[i].isNumeric;
addChild(b);
_header.addItem(b)
}
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void{
super.updateDisplayList(unscaledWidth,unscaledHeight);
for(var i:int=0;i<_header.length;i++){
var b:Object=_header.getItemAt(i);
b.x=this.width/_header.length*i
b.y=-22;
b.width=this.width/_header.length;
b.height=22;
b.buttonMode=true;
b.addEventListener(MouseEvent.CLICK,handleDownSortBtn)
}
}
private function handleDownSortBtn(e:MouseEvent=null):void{
try{
if(_currentSort.fields[0].name==e.target.field){
var desc:Boolean=!_currentSort.fields[0].descending
}
}catch(e:*){
desc=false;
}
_currentSort = new Sort();
_currentSort.fields = [new SortField(e.target.field,true,desc,e.target.isNumeric)];
sortIt(_currentSort)
for(var i:int=0;i<_header.length;i++){
var b:Object=_header.getItemAt(i);
if(b!=e.target){
b.restoreDefault();
}
}
}
public function set sortStyleName(value:Object):void{
for(var i:int=0;i<_header.length;i++){
var b:Object=_header.getItemAt(i);
b.styleName=value;
}
}
private function sortIt(sort:Sort):void{
dataProvider.sort = sort;
dataProvider.refresh();
}
}
}
The SortObject.as:
package it.creativesource
{
public class SortObject
{
public function SortObject(field:String){
this.field=field
}
public var label:String="";
public var field:String="";
public var isNumeric:Boolean=false;
}
}
The SortBtn.as:
package it.creativesource
{
import flash.events.MouseEvent;
import mx.controls.Button;
import mx.controls.Image;
public class SortBtn extends Button
{
public function SortBtn()
{
super();
arrow.source=arrowImage;
}
[Embed(source="assets/arrow.swf" , symbol="arrow" )]
[Bindable]
public var arrowImage:Class;
private var arrow:Image=new Image();
private var _isDown:Boolean=false;
override protected function createChildren():void{
super.createChildren();
addChild(arrow);
arrow.alpha=.5;
arrow.visible=false;
}
override protected function mouseDownHandler(event:MouseEvent):void{
super.mouseDownHandler(event);
_isDown=true
}
public function restoreDefault():void{
arrow.rotation=0
arrow.visible=false
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void{
super.updateDisplayList(unscaledWidth,unscaledHeight)
if(_isDown){
arrow.visible=true;
swapChildren(arrow,this.getChildAt(this.numChildren-2));
arrow.alpha=.2
_isDown=false;
arrow.rotation+=180
}else{
swapChildren(arrow,this.getChildAt(this.numChildren-3));
arrow.alpha=.5
}
arrow.width=10;
arrow.height=7;
arrow.x=this.width-13;
arrow.y=10;
}
public var field:String="";
public var isNumeric:Boolean=false;
}
}
The DisplayItem.mxml:
<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" borderStyle="solid" height="124" width="99">
<mx:Label x="10" y="11" text="Field1"/>
<mx:Text x="55" y="11" text="{data.field1}" width="35" height="18"/>
<mx:Label x="10" y="37" text="Field2"/>
<mx:Text x="56" y="37" text="{data.field2}" width="35" height="18"/>
<mx:Label x="10" y="63" text="Field3"/>
<mx:Text x="56" y="63" text="{data.field3}" width="35" height="18"/>
</mx:Canvas>
