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>
Related
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.
Im working on a display that starts with a centered logo and menu. When one of the menu items is clicked I move the logo and menu to the left side and show a datagrid on the right. Is there a way to use an easing function to make this change look better?
The short answer is: Yes! To illustrate it I've created the following sample:
<?xml version="1.0" encoding="utf-8"?>
<s:Application minHeight="600" minWidth="955" xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:s="library://ns.adobe.com/flex/spark">
<fx:Declarations>
<s:Bounce id="easer1" />
<s:Elastic id="easer2" />
</fx:Declarations>
<s:states>
<s:State name="intro" />
<s:State name="main" />
</s:states>
<s:transitions>
<s:Transition fromState="intro" toState="main">
<s:Sequence>
<s:Move disableLayout="true" easer="{easer2}" target="{menuGroup}" />
<s:SetAction property="verticalCenter" target="{menuGroup}" value="{NaN}" />
<s:SetAction property="horizontalCenter" target="{menuGroup}" value="{NaN}" />
<s:AddAction target="{dg}" />
<s:Fade easer="{easer1}" target="{dg}" />
</s:Sequence>
</s:Transition>
</s:transitions>
<s:VGroup horizontalCenter.intro="0" id="menuGroup" left.main="10" top.main="10" verticalCenter.intro="0">
<s:Label text="Logo is here" />
<s:Button click="currentState = 'main'" label="Click Me!" />
<s:Button click="currentState = 'main'" label="Click Me!" />
</s:VGroup>
<mx:DataGrid bottom="10" id="dg" includeIn="main" left="{menuGroup.width + 20}" right="10" top="10">
<mx:columns>
<mx:DataGridColumn headerText="First" />
<mx:DataGridColumn headerText="Second" />
</mx:columns>
</mx:DataGrid>
</s:Application>
I have a test application here which was made using the following code:
<fx:Script>
<![CDATA[
public function comboBoxHandler():void{
var selectedItem:String = showComboBox.selectedItem;
if(selectedItem == "All results"){
currentState = "default";
return;
}else if(selectedItem == "Only results within tags"){
currentState = "tagInput";
return;
}
}
]]>
</fx:Script>
<s:states>
<s:State name="default"/>
<s:State name="tagInput"/>
</s:states>
<s:transitions>
<s:Transition id="showTagTextInput" fromState="default" toState="tagInput">
<s:Sequence id="t1p1" targets="{[tagsLabel,tagsTextInput,GoButton]}">
<s:Move duration="700"/>
<s:Fade duration="400"/>
</s:Sequence>
</s:Transition>
<s:Transition id="hideTagTextInput" fromState="tagInput" toState="default">
<s:Sequence id="t2p1" targets="{[tagsLabel,tagsTextInput,GoButton]}" >
<s:Fade duration="400"/>
<s:Move duration="700"/>
</s:Sequence>
</s:Transition>
</s:transitions>
<s:Label x="136" y="13" width="120" height="34" fontFamily="Arial" fontSize="15"
text="Lessons
Learnt" textAlign="center"/>
<s:Group id="group" width="100%" height="100%"
x.default="0" y.default="55" width.default="400" height.default="231"
y.tagInput="55" height.tagInput="256">
<s:Label x="45" y="38" width="50" height="22" text="Search" textAlign="center"
verticalAlign="middle"/>
<s:TextInput x="103" y="38" width="193"
useHandCursor.tagInput="false"/>
<s:Label x="45" y="89" width="51" height="22" text="Show" textAlign="center"
verticalAlign="middle"/>
<s:Button id="GoButton" x="253" y="137" width="43" label="Go" useHandCursor="true"
buttonMode="true" mouseChildren="false"
x.tagInput="254" y.tagInput="188"/>
<s:DropDownList id="showComboBox" x="104" y="89" width="192" change="comboBoxHandler();"
selectedIndex="0">
<s:ArrayCollection>
<fx:String>All results</fx:String>
<fx:String>Only results within tags</fx:String>
</s:ArrayCollection>
</s:DropDownList>
<s:Label id="tagsLabel" includeIn="tagInput" x="104" y="146" width="61" height="20" text="Tags"
textAlign="center" verticalAlign="middle"/>
<s:TextInput id="tagsTextInput" includeIn="tagInput" x="173" y="146" width="123"/>
</s:Group>
You can check, by clicking the link I gave, that this app performs some basic transition effect when you select different options from the DropDownBox.
The first (show) transition doesn't work so well, but the second (hide) transition does.
Does anyone know how to fix that? In the first transition, I would like the button to slide down first, only after that should the text input fade In. Why isn't this working?
Thanks in advance.
It is better to point particular effect target rather that pointing all the targets in <s:Sequence />. So place targets to <s:Move /> and <s:Fade />. Also you can perform additional transitions tuning by placing <s:AddAction /> and <s:RemoveAction /> with corresponding targets to point a place within sequence where transition should invoke includeIn and excludeFrom states declarations.
So these transitions works fine with your code:
<s:transitions>
<s:Transition fromState="default" id="showTagTextInput" toState="tagInput">
<s:Sequence id="t1p1">
<s:Move duration="700" targets="{[GoButton]}" />
<s:AddAction targets="{[tagsLabel,tagsTextInput]}" />
<s:Fade duration="400" targets="{[tagsLabel,tagsTextInput]}" />
</s:Sequence>
</s:Transition>
<s:Transition fromState="tagInput" id="hideTagTextInput" toState="default">
<s:Sequence id="t2p1">
<s:Fade duration="400" targets="{[tagsLabel,tagsTextInput]}" />
<s:RemoveAction targets="{[tagsLabel,tagsTextInput]}" />
<s:Move duration="700" targets="{[GoButton]}" />
</s:Sequence>
</s:Transition>
</s:transitions>
I would imagine it's because your tag input is only being included in the tagInput state, but the alpha is 100% and there's no transition between the states. Try this:
<s:Label id="tagsLabel" alpha.default="0" alpha.tagInput="100" x="104" y="146" width="61" height="20" text="Tags" textAlign="center" verticalAlign="middle"/>
<s:TextInput id="tagsTextInput" alpha.default="0" alpha.tagInput="100" x="173" y="146" width="123"/>
You might also want to set visible to false during 'default' state. Also, what Constantiner said is true.
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 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