Is there an easy way, using only MXML, to transition between states that add and remove elements.
For example:
<s:Group includeIn="state1"/>
<s:Group includeIn="state2"/>
Can MXML transitions slide state1 out and state2 in, for example?
Thank you.
In addition to the link posted above here's a way to apply a single transition to multiple targets:
<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:views="views.*" >
<s:states>
<s:State name="home"/>
<s:State name="help"/>
<s:State name="instructions"/>
<s:State name="settings"/>
<s:State name="feedback"/>
</s:states>
<s:transitions>
<s:Transition fromState="*" toState="*" >
<s:Sequence >
<s:Wipe direction="right" duration="350" target="{this}"/>
</s:Sequence>
</s:Transition>
</s:transitions>
<views:Home id="home" includeIn="home" width="100%" height="100%" ownerComponent="{this}"/>
<views:Help id="help" includeIn="help" width="100%" height="100%" ownerComponent="{this}" />
<views:Instructions id="instructions" includeIn="instructions" width="100%" height="100%" ownerComponent="{this}" />
<views:Settings id="settings" includeIn="settings" width="100%" height="100%" ownerComponent="{this}" />
<views:Feedback id="feedback" includeIn="feedback" width="100%" height="100%" ownerComponent="{this}" />
</s:Group>
The previous transition creates a wipe from one direction to the other.
The next transition fades from one view to another:
<s:transitions>
<s:Transition fromState="*" toState="home" >
<s:Sequence >
<s:Fade target="{this}" alphaFrom="1" alphaTo="0"/>
<s:RemoveAction targets="{[home,help,instructions,settings,feedback]}"/>
<s:AddAction target="{home}"/>
<s:Fade target="{this}" alphaFrom="0" alphaTo="1"/>
</s:Sequence>
</s:Transition>
</s:transitions>
The next slides one view in while sliding the rest out:
<s:transitions>
<s:Transition fromState="*" toState="home" >
<s:Sequence duration="1000" >
<s:Parallel>
<s:Move applyChangesPostLayout="true" targets="{notHomeTargets}" xFrom="0" xTo="{-width}"/>
<s:AddAction target="{home}" />
<s:Move applyChangesPostLayout="true" target="{home}" xFrom="{width}" xTo="0"/>
</s:Parallel>
<s:RemoveAction targets="{targets}" />
</s:Sequence>
</s:Transition>
</s:transitions>
You would have to create one for each state with the last examples.
I already had another question on this issue which was successfully resolved. But now, with a slightly different example, I'm stuck again.
I have two states. When I switch from A to B, it resizes correctly, but when I switch from B back to A it happens without the smooth resize transition. What am I doing wrong?
Here's my code:
<fx:Script>
<![CDATA[
protected function rollOverHandler(event:MouseEvent):void
{
this.currentState = "AB";
}
protected function rollOutHandler(event:MouseEvent):void
{
this.currentState = "A";
}
]]>
</fx:Script>
<fx:Declarations>
</fx:Declarations>
<s:states>
<s:State name="A" />
<s:State name="AB" />
</s:states>
<s:transitions>
<s:Transition fromState="A" toState="AB" autoReverse="true">
<s:Parallel>
<s:AddAction target="{controls}"/>
<s:Resize duration="500" target="{controls}" heightFrom="0" />
</s:Parallel>
</s:Transition>
<s:Transition fromState="AB" toState="A" autoReverse="true">
<s:Parallel>
<s:Resize duration="500" target="{controls}" heightTo="0" />
<s:RemoveAction target="{controls}"/>
</s:Parallel>
</s:Transition>
</s:transitions>
<s:BorderContainer width="300"
backgroundColor="#eeeeee"
borderVisible="false"
minHeight="0">
<s:layout>
<s:VerticalLayout gap="0"/>
</s:layout>
<s:VGroup id="data">
<s:Label text="A" fontSize="40" />
</s:VGroup>
<s:VGroup id="controls"
clipAndEnableScrolling="true"
itemCreationPolicy="immediate"
includeIn="AB">
<s:Label text="B" fontSize="40" />
</s:VGroup>
</s:BorderContainer>
</s:HGroup>
Thanks in advance,
Nuno
You need to use a Sequence instead of a Parallel.
I have two states. When I switch from OFF to A, it resizes correctly, but when I switch from A back to OFF it happens without the smooth resize transition. What am I doing wrong?
Here's my code:
<?xml version="1.0" encoding="utf-8"?>
<s:VGroup xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
<fx:Script>
<![CDATA[
protected function butA_changeHandler(e:Event):void
{
if ((e.target as ToggleButton).selected) {
this.currentState="A";
} else {
this.currentState="off";
}
}
]]>
</fx:Script>
<s:states>
<s:State name="off" />
<s:State name="A" />
</s:states>
<s:transitions>
<s:Transition fromState="off" toState="A" autoReverse="true">
<s:Parallel duration="300">
<s:Resize target="{content}" heightTo="{cA.height}" />
<s:Fade targets="{cA}"/>
</s:Parallel>
</s:Transition>
<s:Transition fromState="A" toState="off" autoReverse="true">
<s:Parallel duration="300">
<s:Resize target="{content}" heightTo="0" />
<s:Fade targets="{cA}"/>
</s:Parallel>
</s:Transition>
</s:transitions>
<s:Group id="content" excludeFrom="off" width="100%" clipAndEnableScrolling="true">
<s:Group id="cA" includeIn="A" width="100%"><s:Label fontSize="70" text="A"/></s:Group>
</s:Group>
<s:HGroup>
<s:ToggleButton id="butA" label="A" change="butA_changeHandler(event)"/>
</s:HGroup>
</s:VGroup>
Thanks in advance,
Nuno
You should be using both AddAction and RemoveAction as the includeIn and excludeFrom properties are processed before transitions:
.
<s:transitions>
<s:Transition fromState="off" toState="A" autoReverse="true">
<s:Sequence>
<s:AddAction target="{content}" />
<s:Parallel duration="300">
<s:Resize target="{content}" heightTo="{cA.height}" />
<s:Fade targets="{cA}"/>
</s:Parallel>
</s:Sequence>
</s:Transition>
<s:Transition fromState="A" toState="off" autoReverse="true">
<s:Sequence>
<s:Parallel duration="300">
<s:Resize target="{content}" heightTo="0" />
<s:Fade targets="{cA}"/>
</s:Parallel>
<s:RemoveAction target="{content}" />
</s:Sequence>
</s:Transition>
</s:transitions>
<s:Group id="content" width="100%" clipAndEnableScrolling="true">
<s:Group id="cA" includeIn="A" width="100%"><s:Label fontSize="70" text="A"/></s:Group>
</s:Group>
Start the resizes off from the dimensions you want using heightFrom and widthFrom so that they actually animate.
*Note: Using an includeIn="A" means you are also implying that conent will have the excludeFrom="OFF" property. This means you won't be able to mix Add/RemoveAction and includeIn/excludeFrom (one for adding views and another for removing them).
autoreverseset to true must be redundant with your second transition. It already defines A to off. Just add a heightFromin the first transition.
I would like to write a transition where all the elements from State1 rotate around Y axis and then show elements from State2
This s illustrated in the dummy code below (just imagine Label 1 is a Group).
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
<s:states>
<s:State name="State1"/>
<s:State name="State2"/>
</s:states>
<s:transitions>
<s:Transition fromState="*" toState="State2" autoReverse="true">
<s:Rotate3D target="{label2}" angleYFrom="-90" angleYTo="0" autoCenterTransform="true" duration="1000"/>
</s:Transition>
</s:transitions>
<fx:Declarations>
<s:Rotate3D id="phaseOut" target="{label1}" angleYFrom="0" angleYTo="90" autoCenterTransform="true" duration="1000" effectEnd="currentState='State2'" />
</fx:Declarations>
<s:Label id="label1" includeIn="State1" text="This is state 1" horizontalCenter="0" verticalCenter="0"/>
<s:Label id="label2" includeIn="State2" text="This is state 2" horizontalCenter="0" verticalCenter="0"/>
<s:Button label="Change" horizontalCenter="0" verticalCenter="30" click.State1="phaseOut.play()" click.State2="currentState='State1'"/>
</s:WindowedApplication>
My first problem is when the state transition is invoked, all elements from State1 are already gone, hence I have to split the transition in two hacks (see "phaseOut")
This seems really poor since I am essentially rewritting the transition mechanism.
Q1: Is there a "clean" way to transition elements that do not belong to State2 ?
The second problem is when you revert back to State 1, elements have been rotated.
Q2: Is there such a thing as "autoReverse" for animations?
Thanks for your time!
Instead of doing two transitions, you can add the 'remove' filter to isolate an effect just on items being removed and use the RemoveChildAction to let the transition know when to execute the action to remove the items.
Info on RemoveChildAction:
http://livedocs.adobe.com/flex/3/langref/mx/effects/RemoveChildAction.html
Info on filters:
http://livedocs.adobe.com/flex/3/langref/mx/effects/Effect.html#filter
Effects have a reverse method to play it in reverse:
http://livedocs.adobe.com/flex/3/langref/mx/effects/Effect.html#reverse%28%29
Although I've heard mixed results from people about how successful it is.
Using viewstacks seems to do the trick nicely:
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" >
<fx:Declarations>
<s:Rotate3D id="phaseOut" angleYFrom="0" angleYTo="90" duration="500" autoCenterTransform="true" />
<s:Rotate3D id="phaseIn" angleYFrom="-90" angleYTo="0" duration="500" autoCenterTransform="true" startDelay="500" />
</fx:Declarations>
<mx:ViewStack id="viewstack1" width="200" height="200" horizontalCenter="0" verticalCenter="0">
<s:NavigatorContent label="View 1" width="100%" height="100%" hideEffect="{phaseOut}" showEffect="{phaseIn}" >
<s:Label id="label1" text="This is state 1" horizontalCenter="0" verticalCenter="0"/>
</s:NavigatorContent>
<s:NavigatorContent label="View 2" width="100%" height="100%" hideEffect="{phaseOut}" showEffect="{phaseIn}">
<s:Label id="label2" text="This is state 2" horizontalCenter="0" verticalCenter="0"/>
</s:NavigatorContent>
</mx:ViewStack>
<s:Button label="Toggle" click="viewstack1.selectedIndex=(viewstack1.selectedIndex==0?1:0)" horizontalCenter="0" top="10"/>
</s:Application>
The code is neat and the effect is exactely as expected
I am trying to create the transition between states. The first state transition works fine(state1=>state2), but the second one is acting weird(state2=>state3). After clicks the button to change
state2=>state3, some text areas which are belong to state2 show up and stay on the screen. I am not sure why. I would appreciate it if someone here can help me out.
My code.
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
<fx:Script>
<![CDATA[
protected function btn1_clickHandler(event:MouseEvent):void
{
currentState="state2";
}
protected function btn2_clickHandler(event:MouseEvent):void
{
currentState="state3";
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:states>
<s:State name="state1"/>
<s:State name="state2"/>
<s:State name="state3"/>
</s:states>
<s:transitions>
<s:Transition toState="state2" >
<s:Parallel>
<s:Move targets="{[btn1,btn2]}" />
<s:AddAction targets="{[label1,label2,label3,textInput1,textInput2,textInput3]}" />
<s:Fade targets="{[label1,label2,label3,textInput1,textInput2,textInput3]}"/>
</s:Parallel>
</s:Transition>
<s:Transition toState="state3" >
<s:Fade targets="{[label1,label2,label3,textInput1,textInput2,textInput3]}"/>
</s:Transition>
</s:transitions>
<s:Label y="10" text="label1" id="label1" includeIn="state2" />
<s:TextInput y="30" id="textInput1" includeIn="state2" />
<s:Label y="50" text="label1" id="label2" includeIn="state2" />
<s:TextInput y="70" id="textInput2" includeIn="state2" />
<s:Label y="90" text="label1" id="label3" includeIn="state2" />
<s:TextInput y="120" id="textInput3" includeIn="state2" />
<s:Button y="180" y.state2="350" label="btn1" id="btn1" click="btn1_clickHandler(event)"/>
<s:Button y="250" y.state2="550" label="btn2" id="btn2" click="btn2_clickHandler(event)"/>
</s:Application>
Your code sample looks incomplete. I think we'll need to see more than just the state and transitions. IF you can provide a full running sample that would be helpful.
I assume this is a sample issue, but in your current code, the transitions toStates are not created in the document. Since you have three states, you may want to add a 'fromState' and explicitly design the transition from / to each state.
If I had to guess, you probably need to specify the 'includeIn' property on the relevant components. You can use a comma delimited list of states, something like this:
<s:Component includeIn="a" />
<s:Component includeIn="b,c" />
<s:Component includeIn="a,c" />
Where the first component would appear in state a, the second would appear in state b and c, and the third component would appear in state a and c.
Updated Posters Code:
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
<fx:Script>
<![CDATA[
protected function btn1_clickHandler(event:MouseEvent):void
{
currentState="state2";
}
protected function btn2_clickHandler(event:MouseEvent):void
{
currentState="state3";
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:states>
<s:State name="state1"/>
<s:State name="state2"/>
<s:State name="state3"/>
</s:states>
<s:transitions>
<s:Transition toState="state2" >
<s:Parallel>
<s:Move targets="{[btn1,btn2]}" />
<!--<s:AddAction targets="{[label1,label2,label3,textInput1,textInput2,textInput3]}" /> -->
<s:Fade targets="{[label1,label2,label3,textInput1,textInput2,textInput3]}" alphaFrom="0" alphaTo="1"/>
</s:Parallel>
</s:Transition>
<s:Transition toState="state3" >
<s:Parallel>
<!-- <s:Move targets="{[btn1,btn2]}" />-->
<!--<s:RemoveAction targets="{[label1,label2,label3,textInput1,textInput2,textInput3]}" /> -->
<s:Fade targets="{[label1,label2,label3,textInput1,textInput2,textInput3]}" alphaFrom="1" alphaTo="0"/>
</s:Parallel>
</s:Transition>
</s:transitions>
<s:Label y="10" text="label1" id="label1" includeIn="state2" />
<s:TextInput y="30" id="textInput1" includeIn="state2" />
<s:Label y="50" text="label2" id="label2" includeIn="state2" />
<s:TextInput y="70" id="textInput2" includeIn="state2" />
<s:Label y="90" text="label3" id="label3" includeIn="state2" />
<s:TextInput y="120" id="textInput3" includeIn="state2" />
<s:Button y="180" y.state2="350" includeIn="state1,state2,state3" label="To State 2" id="btn1" click="btn1_clickHandler(event)"/>
<s:Button y="250" y.state2="550" includeIn="state1,state2,state3" label="To State 3" id="btn2" click="btn2_clickHandler(event)"/>
</s:Application>