Flex 3.0 is awesome! Flex 3.0 beta is out now, production version is due out around February 2008.
With Flex 3.0 you can EASILY do animation effects with adding and removing items from the TileList.
Here is an example of what I’ll show you how to code:
Let’s start out with the data that we’ll use. I’ll start with an array called mydata, each item with a name and an age:
public var mydata:Array=[
{name:"A",age:16},
{name:"B",age:17},
{name:"C",age:18},
{name:"D",age:19},
{name:"E",age:20},
{name:"F",age:21},
{name:"G",age:22},
{name:"H",age:23},
{name:"I",age:24},
{name:"J",age:25},
{name:"K",age:26}];
Then create an ArrayCollection called myAC initialized with mydata.
public var myAC:ArrayCollection = new ArrayCollection(mydata);
As we remove items from the TileList we’ll need someplace to keep them in case we need to display them again later, so declare another ArrayCollection for this task.
private var hidden:ArrayCollection = new ArrayCollection;
We’ll have two ArrayCollections one for the display and one for the non-display items. All items will be on one of these lists. As we delete one item, we’ll remove it from the display list and put it on the hidden list. As we add an item to the display list, we’ll remove it from the hidden list. An item will either be on the display list or the hidden list.
Let’s build the TileList to display the data, give it an id of ‘tlist’, height and width of 400, make it a 4×4 grid with the Data direction of horizontal. New with Flex 3 are parameters: offscreenExtraColumns, offscreenExtraRows, and dataChangeEffect. The manual says to use 2 or a multiple of 2 for both offscreenExtraColumns and offScreenExtraRows, however when I tried that, Then some of the display items disappeared, zero appears to work fine, but you may want to try out the values 2 or 4 with your setup. The new ListBase property offscreenExtraRows and offscreenExtraColumns helps to eliminate visual glitches in data effects. Setting this property to a small even number such as 2 or 4, or possibly larger if many items may be deleted at once, is recommended.
<mx:TileList id="tlist"
height="400" width="400"
fontSize="30" fontStyle="bold"
columnCount="4" rowCount="4"
direction="horizontal"
dataProvider="{myDP}"
itemRenderer="Thumbnail"
offscreenExtraColumns="0"
offscreenExtraRows="0"
dataChangeEffect="{dataChangeEffect1}"/>
The TileList uses a custom itemRenderer so let’s create the itemRenderer: create a new MXML component called ‘Thumbnail.mxml’ with
Two labels inside a VBox with size 100×100:
<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" width="100" height="100">
<mx:Label text="{data.name}" />
<mx:Label text="{data.age}" />
</mx:VBox>
Next let’s add two numeric steppers that will allow us to interact with the data in the TileList, the two steppers will define a range of values that are viewable. Shrinking the range of numbers will delete those data items in the TileList, while expanding the range will bring the data back into view. Create a HBox, add a label and then create a NumericStepper with a range of 14-26, and a current value of ‘24’, set the stepSize to 1, and when this value changes, make a call to lowchange().
<mx:HBox >
<mx:Label text="Lowest Value:" />
<mx:NumericStepper id="low" value="24" minimum="14" maximum="26" stepSize="1" change="lowchange()" />
</mx:HBox>
Create another NumericStepper to act as the higher range, setting the value to 26, and call highchange() when the user changes this value.
<mx:HBox >
<mx:Label text="Highest Value:" />
<mx:NumericStepper id="high" value="26" minimum="17" maximum="26" stepSize="1" change="highchange()"/>
</mx:HBox>
Now for the real code – what is required is the index value of the items that will be deleted and calling removeItemAt() for the effect to play. In the lowchange function we search for values that are outside the range specified by the two numeric steppers. Loop thru all the values of the ArrayCollection (myAC), when a value is found less than the lower limit, add the index (removelist.push(j)) to a list of items to remove. As we look for items to remove, copy the items that we remove to another list (hidden) so that we can add these items back later when the lower limit changes again. i.e. there will be two lists – one containing the items outside the range, and another containing all the items within the range which will be displayed.
private function lowchange():void {
var removelist:Array = []; // an array of indexes of items to remove
for (var j:int = 0; j < myAC.length; j++){
if (myAC[j].age < low.value) {
hidden.addItem(myAC[j]); // copy item to remove to hidden list
removelist.push(j); // keep index of item to remove, so that we can remove in next step
}
}
At this point we have a list of indices to the items that we need to remove, next the list is sorted in descending order and then step thru the list removing items one by one from the end of the array. If the remove list is not sorted descending is to prevent us from stepping on ourselves. For example if the remove list contains indices 2 and 4, and you remove item at index #2, then the item at index #4 moves up one to become index #3, then if you remove the item at index #4, this is really the item at index #5. Removing them from the end solves this problem.
removelist.sort(Array.DESCENDING); // sort list so that we can start deleting from end of the list
for (var i:int = 0; i < removelist.length; i++) {
myAC.removeItemAt(removelist[i]); // remove item
}
Next, let’s look thru the hidden list and see if any items need to be moved back to the display. Loop thru the hidden list checking values that are inside the range, if found then user the random function to insert them back in at a random place. Keep a list of the items added so that they can be removed from the hidden list. Here is the code:
/* look thru hidden list and see if we need to add any items back */
var addlist:Array = []; // an array of indexes of items to remove
for ( j = 0; j < hidden.length; j++){
if ((hidden[j].age >= low.value) && (hidden[j].age <=high.value) ) {
myAC.addItemAt(hidden[j], Math.floor(Math.random() * myAC.length )); // copy item to a random spot (and later remove from hidden list)
addlist.push(j); // keep index of item to add, so that we can remove in next step
}
}
addlist = addlist.sort(Array.DESCENDING); // sort list so that we can start deleting from end of the list
for (i = 0; i < addlist.length; i++) {
hidden.removeItemAt(addlist[i]); // remove item from hidden list
}
}
Next. Let’s add the effect that gets played when an item is added or removed:
<mx:DefaultListEffect id="myDLE"
fadeOutDuration="1000"
fadeInDuration="350"
color="0x0044ff"/>
That’s it! Here is the complete code for the main component, (following is the code for the itemrenderer):
<?xml version="1.0"?>
<!-- dataEffects\CustomTileListEffect.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:comp="*" >
<mx:Script>
<![CDATA[
import mx.effects.easing.Elastic;
import mx.collections.ArrayCollection;
public var mydata:Array=[
{name:"A",age:14},
{name:"B",age:15},
{name:"C",age:16},
{name:"D",age:17},
{name:"E",age:18},
{name:"F",age:19},
{name:"G",age:20},
{name:"H",age:21},
{name:"I",age:22},
{name:"J",age:23},
{name:"J",age:24},
{name:"J",age:25},
{name:"K",age:26}];
[Bindable]
public var myAC:ArrayCollection = new ArrayCollection(mydata);
private var hidden:ArrayCollection = new ArrayCollection;
private function lowchange():void {
var removelist:Array = []; // an array of indexes of items to remove
for (var j:int = 0; j < myAC.length; j++){
if (myAC[j].age < low.value) {
hidden.addItem(myAC[j]); // copy item to remove to hidden list
removelist.push(j); // keep index of item to remove, so that we can remove in next step
}
}
removelist.sort(Array.DESCENDING); // sort list so that we can start deleting from end of the list
for (var i:int = 0; i < removelist.length; i++) {
myAC.removeItemAt(removelist[i]); // remove item
}
/* look thru hidden list and see if we need to add any items back */
var addlist:Array = []; // an array of indexes of items to remove
for ( j = 0; j < hidden.length; j++){
if ((hidden[j].age >= low.value) && (hidden[j].age <=high.value) ) {
myAC.addItemAt(hidden[j], Math.floor(Math.random() * myAC.length )); // copy item to a random spot (and later remove from hidden list)
addlist.push(j); // keep index of item to add, so that we can remove in next step
}
}
addlist = addlist.sort(Array.DESCENDING); // sort list so that we can start deleting from end of the list
for (i = 0; i < addlist.length; i++) {
hidden.removeItemAt(addlist[i]); // remove item from hidden list
}
}
private function highchange():void {
var s:int = 0;
var randm:int = 0;
for ( s = 0; s< 100; s++) {
randm = (Math.floor(Math.random() * myAC.length) );
trace ( "random is " + randm + " leng is " + myAC.length);
}
var removelist:Array = []; // an array of indexes of items to remove
for (var j:int = 0; j < myAC.length; j++){
if (myAC[j].age > high.value) {
hidden.addItem(myAC[j]); // copy item to remove to hidden list
removelist.push(j); // keep index of item to remove, so that we can remove in next step
}
}
removelist.sort(Array.DESCENDING); // sort list so that we can start deleting from end of the list
for (var i:int = 0; i < removelist.length; i++) {
myAC.removeItemAt(removelist[i]); // remove item
}
/* look thru hidden list and see if we need to add any items back */
var addlist:Array = []; // an array of indexes of items to remove
for ( j = 0; j < hidden.length; j++){
if ((hidden[j].age >= low.value) && (hidden[j].age <=high.value) ) {
myAC.addItemAt(hidden[j], Math.floor(Math.random() * myAC.length) ); // copy item to myAC list (and later remove from hidden list)
addlist.push(j); // keep index of item to add, so that we can remove in next step
}
}
addlist = addlist.sort(Array.DESCENDING); // sort list so that we can start deleting from end of the list
for (i = 0; i < addlist.length; i++) {
hidden.removeItemAt(addlist[i]); // remove item from hidden list
}
}
]]>
</mx:Script>
<mx:DefaultListEffect id="myDLE"
fadeOutDuration="1000"
fadeInDuration="350"
color="0x0044ff"/>
<!-- This TileList uses a custom data change effect -->
<!-- offscreenExtraColumns and ..Rows should be 2, but '2' causes items to disappear -->
<mx:TileList id="tlist"
height="400" width="400"
fontSize="30" fontStyle="bold"
columnCount="4" rowCount="4"
direction="horizontal"
dataProvider="{myAC}"
itemRenderer="Thumbnail"
offscreenExtraColumns="0"
offscreenExtraRows="0"
dataChangeEffect="{myDLE}"/>
<mx:HBox >
<mx:Label text="Lowest Value:" />
<mx:NumericStepper id="low" value="16" minimum="14" maximum="26" stepSize="1" change="lowchange()" />
</mx:HBox>
<mx:HBox >
<mx:Label text="Highest Value:" />
<mx:NumericStepper id="high" value="26" minimum="17" maximum="26" stepSize="1" change="highchange()"/>
</mx:HBox>
</mx:Application>
Here is Thumbnail.mxml:
<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" width="100" height="100">
<mx:Label text="{data.name}" />
<mx:Label text="{data.age}" />
</mx:VBox>
Next article will show how to add a few more effects.
Appreciate it for helping out, great info .