How to apply effects to components inside containers with automated layout

In this tutorial I will explain how to apply a tween effect to a component inside a container with automated layout.

Containers like VBox, HBox, Panel(except for layout=absolute), Grid, … automatically position items for you.

Lets try to apply a Move effect to a Button inside a VBox:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" height="500" width="500">
<mx:Script>
 <![CDATA[
     /**
     * This method runs an effect on a button to move it
     * to the right side.
     * 
     */
  public function moveButton(button:Button):void {
   this.moveEffect.target= button;
   this.moveEffect.play();
  }
 ]]>
</mx:Script>
 <mx:VBox id="box" clipContent="false" backgroundAlpha="1" backgroundColor="red">
  <mx:Button id="button1" label="Button 1" click="moveButton(button1)"/>
  <mx:Button id="button2" label="Button 2" click="moveButton(button2)"/>
  <mx:Button id="button3" label="Button 3" click="moveButton(button3)"/>
 </mx:VBox>
  <mx:Sequence id="moveEffect">
   <mx:Move duration="5000" xBy="300" yBy="300"/>
   <mx:Move duration="5000" xBy="-300" yBy="-300"/>
  </mx:Sequence>
</mx:Application>

Click here to run our example

In the example above we set clipContent to false to enable the button to be visible outside the VBox container after it moves.

To start the move effect you need to click in one of the buttons. You will then see the button you clicked move to the right bottom corner and then return to its original position. This example is not completely correct, but it works for this simple example.

To understand why it might not work lets add a Resize effect to the VBox to go along with the button Move effect:

<mx:Parallel id="moveEffect">
 <mx:Sequence>
  <mx:Move duration="5000" xBy="300" yBy="300"/>
  <mx:Move duration="5000" xBy="-300" yBy="-300"/>
 </mx:Sequence>
 <mx:Sequence>
  <mx:Resize target="{box}" duration="5000" heightBy="300" widthBy="300"/>
  <mx:Resize target="{box}" duration="5000" heightBy="-300" widthBy="-300"/>
 </mx:Sequence>
</mx:Parallel>

At the same time that we move the button to the right bottom corner and then back to its origin, we also increase the size of the VBox and then decrease it back to its original size. Note here the use of Sequence and Parallel. These two effects allow us to run a list of child effects in sequence or in parallel as you probably guessed.

Click here to try the example above

Did you notice anything wrong with the example above? Now the Move effect doens’t work anymore. This is because every time we change the size of the VBox, Flex needs to re-position the items inside the VBox. Because of this the x and y values of the button are re-calculated thus ruining our Move effect.
The solution to this problem is to set autoLayout=”false” immediately before the start of the effect:

<mx:VBox id="box" clipContent="false" backgroundAlpha="1" backgroundColor="red">
 <mx:Button id="button1" label="Button 1" click="moveButton(button1)"/>
 <mx:Button id="button2" label="Button 2" click="moveButton(button2)"/>
 <mx:Button id="button3" label="Button 3" click="moveButton(button3)"/>
</mx:VBox>




Click here to see the full working solution in action