View state transition problem: effects don't play

< back to overview

If you are using view states and want to apply certain transitions between these states, there are some things to keep in mind. When adding components to a state, the transition effects (also called behaviors) are applied to that component while adding it. So this means that the effects will be visible during initialization of the view state. However, when you go back to the original base state, the component is removed again before the effects have had the chance of being displayed. Luckily, in Flex there are a couple of ways of dealing with this issue.

The first way of making sure the effects are visible is to not make use of a transition when going back to the base state. Instead, you use the effect triggers of the component itself to trigger the effect. When the component is removed, you need to use the removedEffect trigger like in the following example:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical">

<!-- The font needs to be embedded for the texxt to fade out
as well. Otherwise, the button will fade, but the text
will simply remain fully opaque througout the effect -->
<mx:Style>
@font-face {
src: local("Verdana");
fontFamily: myFont;
fontWeight: bold;
}

global {
fontFamily: myFont;
}
</mx:Style>

<!-- This is the Fade effect we are going to use when the component is removed from the display list -->
<mx:Fade id="fade" alphaFrom="1" alphaTo="0" duration="2000"/>

<!-- Define the view state -->
<mx:states>
<mx:State name="extraButton">
<mx:AddChild>
<!-- This button will fade in through the transitions and will fade out via the removedEffect trigger -->
<mx:Button id="btn2" label="Click me now" click="currentState=''" removedEffect="{fade}"/>
</mx:AddChild>
</mx:State>
</mx:states>

<!-- Define the view state transition -->
<mx:transitions>
<mx:Transition fromState="" toState="extraButton">
<mx:Fade target="{btn2}" alphaFrom="0" alphaTo="1" duration="2000"/>
</mx:Transition>
</mx:transitions>

<!-- This component will be visible by default and triggers the second view state -->
<mx:Button id="btn1" label="Click me" click="currentState='extraButton'"/>

</mx:Application>

The problem with this approach is that the transition effects are scattered throughout your code. However, there is also a second, in my opinion more appropriate way of dealing with this transition problem and that is through the use of transitions. This means that all of your transitional code will be located in 1 spot and this is so much easier to maintain.

But how do we solve the issue of the effect not being shown? Well, in fact (and this is not often mentioned in books and courses), you do have total control of when an item is being added or removed considering the effects that need to be played on the component. To do this, you can simply use the <mx:AddChildAction> and <mx:RemoveChildAction> tags. Just place them in the right order within a <ms:Sequence> tag after the appropriate effect and your effect will be displayed properly. Just take a look at this example code:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">

<!-- The font needs to be embedded for the texxt to fade out as well.
Otherwise, the button will fade, but the text will simply remain fully opaque
througout the effect -->

<mx:Style>
@font-face {
src: local("Verdana");
fontFamily: myFont;
fontWeight: bold;
}

global {
fontFamily: myFont;
}
</mx:Style>

<!-- Define the view state -->
<mx:states>
<mx:State name="extraButton">
<mx:AddChild>
<!-- This button will fade in and out through the transitions -->
<mx:Button id="btn2" label="Click me now" click="currentState=''"/>
</mx:AddChild>
</mx:State>
</mx:states>

<!-- Define the view state transition -->
<mx:transitions>
<mx:Transition fromState="" toState="extraButton">
<mx:Fade target="{btn2}" alphaFrom="0" alphaTo="1" duration="2000"/>
</mx:Transition>

<!-- The fade out effect is accomplished by adding a sequence with the RemoveChildAction after the effect -->
<mx:Transition fromState="extraButton" toState="">
<mx:Sequence target="{btn2}">
<mx:Fade alphaFrom="1" alphaTo="0" duration="2000"/>
<mx:RemoveChildAction/>
</mx:Sequence>
</mx:Transition>
</mx:transitions>

<!-- This component will be visible by default and triggers the second view state -->
<mx:Buttonid="btn1" label="Click me" click="currentState='extraButton'"/>

</mx:Application>

You can view the results of the latter solution in the application below.

This movie requires Flash Player 9

  • Share/Bookmark
< back to overview

Comments

Eric Storm on January 18, 2010 at 5:56 am

Nice tidbit. I wonder if you have one additional piece of helpful info for me.

I’m trying to create a transition effect between many different states. It involves a Canvas, id=”main_content”. In the canvas is the various different “pages” of information, which I am adding using <mx:AddChild relativeTo="{main_content}" etc.

What I wish to do is to have the main_content Canvas do a wipe up, then have the content change, then have the canvas do a wipe down, with the new content. I have the wipes working (finally – that took forever…), but the content is changing immediately…

And here's my problem: I can do an … but how do I target it, when the target will be different for each state?

Hope you can help. Thanks in advance,
Eric


Eric Storm on January 18, 2010 at 5:57 am

Sorry, that line should read “I can do an <AddChildAction>… but how do I…”

Eric


Eric Storm on January 18, 2010 at 6:18 am

One last piece of info… (Sorry, I’m still working on this thing as I search for help…)

Adding an “AddChildAction” or “RemoveChildAction” tag without a target, does not seem to work. The child of main_content is added immediately, anyway, even though the AddChildAction is near the very bottom of my transitions, over a second into the future…

Eric


Steven Peeters on January 18, 2010 at 9:00 am

Hi Eric,

First of all, you need to check something: do you have a target specified in the tag? Because that is where the target is defied in this example, not in the tag.

Secondly, if you have changing targets for each state, you’re definitely better off creating these transitions in ActionScript. That way, you can dynamicall set the target, depending on the view states your working with. Remember, everything you can do in MXML, you can do in ActionScript as well. Sometimes it’s quite a bit harder to implement, but it’ll give you more control over the course of events.

Without looking at the code, I’m afraid I can’t really do anything more than this…

I hope it helps.

Steven


Make a comment