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 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 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>