How can I nicely animate between viewstacks

2019-06-26 09:23发布

问题:

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?

回答1:

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



回答2:

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>


回答3:

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();
}


回答4:

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>