views:

3332

answers:

4

I have a little Adobe Air app and I want to have several 'views' within it. I can achieve these views using a ViewStack but am having difficulty finding a nice way to animate between them.

This is what I have tried and although it works, one view disappears before sliding into view when what I want is more like the DestroyTwitter app where the view and all controls slide out of view nicely:

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="400" height="700" top="100" left="100" creationComplete="onComplete()">
    <mx:Script>
 <![CDATA[
  import mx.core.Application;
  private function onComplete():void
  {
   stack.selectedChild = stack1;
  }

  private function switchTab():void
  {
   if( stack.selectedChild == stack1 )
   {
    stack.selectedChild = stack2;
   }
   else
   {
    stack.selectedChild = stack1;
   }
  }
 ]]>
    </mx:Script>

    <mx:Move id="slideLeft" xFrom="{Application.application.width}" xTo="0" yTo="0" duration="500" />
    <mx:Move id="slideRight" xFrom="0" xTo="{Application.application.width}" duration="500" />

    <mx:ViewStack id="stack" width="200%" height="100%">
     <mx:VBox id="stack1" width="100%" height="100%" backgroundColor="white" hideEffect="{slideRight}" >
      <mx:Label text="Stack 1" />
      <mx:Button label="Switch" click="switchTab()" />
     </mx:VBox>

     <mx:VBox id="stack2" width="100%" height="100%" backgroundColor="#cdcdcd" hideEffect="{slideLeft}" >
      <mx:Label text="Stack 2" />
      <mx:Button label="Switch" click="switchTab()" />
     </mx:VBox>

    </mx:ViewStack>
</mx:WindowedApplication>

Has anyone got any nicer ideas to try, be grateful for any response?

A: 

One thing you can try is a little more advanced swapping in and out of views. When the 'switch' button is clicked, perform the move and don't do the swap until the move is finished.

Perhaps something like this:

private function switchTab():void {

    var move:Move = new Move(stack.selectedChild as DisplayObject); //not sure about the casting right now...might need to check on that
    // implement move details here...

    //closure to make sure the next child is swapped in after the animation completes
    var done:Function = function(event:Event):void {
        // do the change here in this closure
        if (stack.selectedChild == stack1) {
            stack.selectedChild = stack2;
        }
        else {
            stack.selectedChild = stack1;
        }
        // remove the EventListener..don't want memory leaks :)
        move.removeEventListener(EffectEvent.END, done);
    }
    // make sure 'move' performs the 'done' function when the animation finishes
    move.addEventListener(EffectEvent.END, done);

    move.play();
}
bedwyr
Thanks a lot for replying, unfortunately I didnt really get any difference in result than with my attempt. I think the transitions thing on quoo's answer looks like it might be more like the thing that is needed.
Dan
Sounds good -- I didn't try this out, so I didn't observe the behavior =)
bedwyr
+1  A: 

I'd use states that control which view is active, and then define transitions for moving between those states:

http://livedocs.adobe.com/flex/3/html/help.html?content=transitions_3.html

quoo
That looks real interesting, looks like I will need to read through the docs. Thanks.
Dan
Oh good! Sorry I couldn't go into more detail, I'm totally swamped at work right now:) (And... probably shouldn't be checking stack overflow;) )
quoo
Try as I might, I just cant work out the transitions I need to use to get this to work, any help from you or anyone would be greatly appreciated ... Ill keep trying though.
Dan
hmm, maybe this will help?http://www.lennel.org/blog/2006/04/09/some-more-on-viewstacks-and-states/
quoo
Actually got it working now, will take a look at the blog post above later to see if its any different. I have added my answer to this question
Dan
+1  A: 

Here is exactly what i wanted to achieve:

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" 
    layout="absolute" width="400" height="700" top="100" left="100" 
    horizontalScrollPolicy="off" verticalScrollPolicy="off"
    >

    <mx:Script>
     <![CDATA[
      import mx.core.Application;
     ]]>
    </mx:Script>


    <mx:states>
    <mx:State name="One">
      <mx:SetProperty target="{stack1}" name="x" value="0"/>
      <mx:SetProperty target="{stack1}" name="y" value="50"/>
      <mx:SetProperty target="{stack1}" name="width" value="{Application.application.width}"/>

      <mx:SetProperty target="{stack2}" name="x" value="{Application.application.width}"/>
      <mx:SetProperty target="{stack2}" name="y" value="50"/>
      <mx:SetProperty target="{stack2}" name="width" value="{Application.application.width}"/>
    </mx:State>

    <mx:State name="Two">
      <mx:SetProperty target="{stack1}" name="x" value="-{Application.application.width}"/>
      <mx:SetProperty target="{stack1}" name="y" value="50"/>
      <mx:SetProperty target="{stack1}" name="width" value="{Application.application.width}"/>

      <mx:SetProperty target="{stack2}" name="x" value="0"/>
      <mx:SetProperty target="{stack2}" name="y" value="50"/>
      <mx:SetProperty target="{stack2}" name="width" value="{Application.application.width}"/>
    </mx:State>
    </mx:states>


    <!-- Define Transition array with one Transition object.-->
    <mx:transitions>
     <!-- A transition for changing from any state to any state. -->
     <mx:Transition id="myTransition" fromState="*" toState="*">
      <mx:Parallel id="t1" targets="{[stack1,stack2]}">
       <mx:Move   duration="400"/>
      </mx:Parallel>
     </mx:Transition>
    </mx:transitions>

    <mx:HBox>
     <mx:Button label="Switch To Two" click="currentState='Two'" />
     <mx:Button label="Switch To One" click="currentState='One'" />
    </mx:HBox>

    <mx:Canvas id="stack1" x="0" y="50" width="100%" height="100%" borderThickness="1" borderStyle="solid">
     <mx:VBox width="100%" height="100%" backgroundColor="white">
      <mx:Label text="Stack 1" />
      <mx:Box backgroundColor="red" width="20" height="20" />
     </mx:VBox>
    </mx:Canvas>

    <mx:Canvas id="stack2" x="{Application.application.width}" y="50" width="100%" height="100%" borderThickness="1" borderStyle="solid">
     <mx:VBox width="100%" height="100%" backgroundColor="#cdcdcd">
      <mx:Label text="Stack 2" />
      <mx:Box backgroundColor="green" width="20" height="20" />
     </mx:VBox>
    </mx:Canvas>

</mx:WindowedApplication>
Dan
ah good, you figured out the state / transitions thing.
quoo
Yup, thanks a lot for that, exactly what I was looking for
Dan
A: 

Add Blur to the accepted answer above. Makes the transition look smoother/cooler.

I was trying to replicate the state transitions from this cool Arduino speedometer by Mike Chambers, and the answer by Dan with some added Blur did the trick.

<!-- Define Transition array with one Transition object.-->
    <mx:transitions>
        <!-- A transition for changing from any state to any state. -->
        <mx:Transition id="myTransition" fromState="*" toState="*">
            <mx:Sequence id="s1" targets="{[stack1,stack2]}">

                <mx:Blur duration="50" blurXFrom="0.0" blurXTo="5.0"
                         blurYFrom="0.0" blurYTo="5.0"/>

                <mx:Parallel id="t1" targets="{[stack1,stack2]}">
                        <mx:Move duration="400"/>
                </mx:Parallel>

                <mx:Blur duration="50" blurXFrom="5.0" blurXTo="0.0"
                          blurYFrom="5.0" blurYTo="0.0"/>
            </mx:Sequence>

        </mx:Transition>
    </mx:transitions>
Brian Bishop