Adobe Flex 3 Help

Creating a custom data effect

You can create a custom data effect for use with the List and TileList controls. To create a custom data effect, define a Parallel or Sequence effect, and then assign the effect to the itemsChangeEffect property of the control.

Flex defines several action effects so that you can control when items are added, removed, or replaced in the list control as part of the effect, or to allow you to control the layout of item renderers in the control during the effect. The following table describes these action effects:

Action effect class

Use

AddItemAction

Defines an effect that determines when the item renderer appears in the control for an item being added to a list-based control, or for an item that replaces an existing item in the control.

RemoveItemAction

Defines an effect that determines when the item renderer disappears from the control for the item renderer of an item being removed from a list-based control, or for an item that is replaced by a new item added to the control.

UnconstrainItemAction

Defines an effect to temporarily stop item renderers from being positioned by the layout algorithm of the parent control. Use this effect to allow item renderers in a TileList control to move freely rather than being constrained to lay in the normal grid that is defined by the control. You typically add this effect when your custom data effect moves item renderers.

You can use the Effect.filter property to filter possible effect targets, which lets you play an effect only on a subset of the item renderers in the list-based control. The following table lists the values of the Effect.filter property that you use with data effects:

Effect.filter value

Descriptions

addItem

Play the effect on the item renderer for any list items added to a List or TileList control.

removeItem

Play the effect on the item renderer for any list items removed from a List or TileList control.

replacedItem

Play the effect on the item renderer for any list items replaced in a List or TileList control by a new item.

replacementItem

Play the effect on the item renderer for any list items added to a List or TileList control that replaces an existing item.

For detailed information and examples of action effects and effect filters, see Using action effects in a transition and Filtering effects.

Example: Custom data effect

The following example defines a custom data effect for the TileList control. This data effect defines a Sequence effect that contains a Blur effect and a Parallel effect. The data effect performs the following actions when you delete an item from the TileList control:

  • Applies the Blur effect to the item being deleted.
  • Makes the item being deleted invisible.
  • Applies the UnconstrainItemAction effect because you are moving item renderers in the custom effect.
  • Moves the remaining items to their new position.
  • Removes the item being deleted.

The custom data effect performs the following actions when you add an item to the TileList control:

  • Applies the UnconstrainItemAction effect because you are moving item renderers in the custom effect.
  • Moves the existing items to their new position.
  • Adds the new item to the control.
  • Applies a Blur effect to the new item.
<?xml version="1.0"?>
<!-- dataEffects\CustomTileListEffect.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">

    <mx:Script>
        <![CDATA[
            import mx.effects.easing.Elastic;
            import mx.collections.ArrayCollection;
            
            [Bindable]
            private var myDP:ArrayCollection = new ArrayCollection(
                ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q']);
            
            private function deleteItem():void {
                // As each item is removed, the index of the other items changes.
                // So first get the items to delete, and then determine their indices
                // as you remove them.
                var toRemove:Array = [];
                for (var i:int = 0; i < tlist0.selectedItems.length; i++)
                    toRemove.push(tlist0.selectedItems[i]);
                for (i = 0; i < toRemove.length; i++)
                    myDP.removeItemAt(myDP.getItemIndex(toRemove[i]));
            }

            private var zcount:int = 0;
            private function addItem():void {
                // Always add the new item after the third item,
                // or after the last item if the length is less than 3.
                myDP.addItemAt("Z"+zcount++,Math.min(3,myDP.length));
            }                        
        ]]>
    </mx:Script>

    <!-- Define a custom data effect as a Sequence effect. -->
    <mx:Sequence id="dataChangeEffect1">
        <mx:Blur 
            blurYTo="12" blurXTo="12" 
            duration="300" 
            perElementOffset="150"
            filter="removeItem"/> 
        <mx:SetPropertyAction 
            name="visible" value="false" 
            filter="removeItem"/>    
        <mx:UnconstrainItemAction/>
        <mx:Parallel>
            <mx:Move 
                duration="750" 
                easingFunction="{Elastic.easeOut}" 
                perElementOffset="20"/>
            <mx:RemoveItemAction 
                startDelay="400" 
                filter="removeItem"/>
            <mx:AddItemAction  
                startDelay="400" 
                filter="addItem"/>
            <mx:Blur 
                startDelay="410" 
                blurXFrom="18" blurYFrom="18" blurXTo="0" blurYTo="0" 
                duration="300" 
                filter="addItem"/>
        </mx:Parallel>
    </mx:Sequence>        

    <!-- This TileList uses a custom data change effect. -->
    <mx:TileList id="tlist0" 
        height="400" width="400" 
        fontSize="30" fontStyle="bold"
        columnCount="4" rowCount="4" 
        direction="horizontal" 
        dataProvider="{myDP}" 
        allowMultipleSelection="true" 
        offscreenExtraRowsOrColumns="4" 
        itemsChangeEffect="{dataChangeEffect1}"/>

    <mx:Button 
        label="Delete selected item(s)" 
        click="deleteItem();"/>
    <mx:Button 
        label="Add item" 
        click="addItem();"/>
</mx:Application>

The executing SWF file for the previous example is shown below:

This example uses the Effect.filter property to filter possible effect targets. Because you set the filter property of the first Blur effect to removeItem, Flex only applies the effect to items added to the list control. Because the Move effect omits the filter property, Flex applies the effect to all items in the control.

You can create a custom filter by passing an instance of the EffectTargetFiler class to the Effect.customFilter property. For example, the Effect.filter property lets you specify only a single value, such as addItem or removeItem. However, you can use the EffectTargetFiler.requiredSemantics property to specify a collection of properties and associated values that must be associated with a target for the effect to be played. For more information, see Filtering effects.

Debugging a custom data effect

When debugging a custom data effect, you should set the Effect.suspendBackgroundProcessing property to true. If true, the suspendBackgroundProcessing property blocks all background processing while an effect is playing, and can help to reduce any flickering caused by the effect. Background processing includes measurement, layout, and processing responses that have arrived from the server.

Creating a custom data effect in a separate MXML file

You can write your custom data effect as an MXML component, as the following example shows:

<?xml version="1.0"?>
<!-- dataEffects\myComponents\MyDataEffect.mxml -->
<mx:Sequence xmlns:mx="http://www.adobe.com/2006/mxml">

    <mx:Script>
        <![CDATA[
            import mx.effects.easing.Elastic;
        ]]>
    </mx:Script>

    <!-- Define a custom data effect as a Sequence effect. -->
    <mx:children>
        <mx:Blur 
            blurYTo="12" blurXTo="12" 
            duration="300" 
            perElementOffset="150"
            filter="removeItem"/>
        <mx:SetPropertyAction 
            name="visible" value="false" 
            filter="removeItem"/>    
        <mx:UnconstrainItemAction/>
        <mx:Parallel>
            <mx:Move 
                duration="750" 
                easingFunction="{Elastic.easeOut}" 
                perElementOffset="20"/>
            <mx:RemoveItemAction 
                startDelay="400" 
                filter="removeItem"/>
            <mx:AddItemAction  
                startDelay="400" 
                filter="addItem"/>
            <mx:Blur 
                startDelay="410" 
                blurXFrom="18" blurYFrom="18" blurXTo="0" blurYTo="0" 
                duration="300" 
                filter="addItem"/>
        </mx:Parallel>
    </mx:children>
</mx:Sequence> 

In this example, you create a custom MXML component based on the Sequence effect. Notice that the component specifies the Sequence.children property, the default MXML property of the Sequence effect class. This tag is necessary in a custom component because custom component do not recognize the default MXML property; therefore, you must specify it. For more information on the default MXML property, see MXML Syntax.

The custom MXML component is in the file MyDataEffect.mxml in the myComponents subdirectory of the main application file. The following example shows the main application that uses this MXML component:

<?xml version="1.0"?>
<!-- dataEffects\CustomTileListEffectComponent.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">

    <mx:Script>
        <![CDATA[
            import mx.collections.ArrayCollection;
            import myComponents.MyDataEffect;
            
            [Bindable]
            private var myDP:ArrayCollection = new ArrayCollection(
                ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q']);
            
            private function deleteItem():void {
                // As each item is removed, the index of the other items changes.
                // So first get the items to delete, then determine their indices
                // as you remove them.
                var toRemove:Array = [];
                for (var i:int = 0; i < tlist0.selectedItems.length; i++)
                    toRemove.push(tlist0.selectedItems[i]);
                for (i = 0; i < toRemove.length; i++)
                    myDP.removeItemAt(myDP.getItemIndex(toRemove[i]));
            }

            private var zcount:int = 0;
            private function addItem():void {
                // Always add the new item after the third item,
                // or after the last item if the length is less than 3.
                myDP.addItemAt("Z"+zcount++,Math.min(3,myDP.length));
            }                        
        ]]>
    </mx:Script>

    <!-- This TileList uses a custom data change effect -->
    <mx:TileList id="tlist0" 
        height="400" width="400" 
        fontSize="30" fontStyle="bold"
        columnCount="4" rowCount="4" 
        direction="horizontal" 
        dataProvider="{myDP}" 
        allowMultipleSelection="true" 
        offscreenExtraRowsOrColumns="4" 
        itemsChangeEffect="{MyDataEffect}"/>

    <mx:Button 
        label="Delete selected item(s)" 
        click="deleteItem();"/>
    <mx:Button 
        label="Add item" 
        click="addItem();"/>
</mx:Application>

The executing SWF file for the previous example is shown below: