取消状态转换并直接转到另一个视图

Canceling a state transition and go directly to another view

我的皮肤有3种状态。我以后可能会有更多的状态。但它是一个正常状态的工具栏,然后是展开视图,一次只能看到一个展开视图。

当我有两个状态时,我可以使用下面的转换代码轻松地在两个状态之间转换。但是现在我有三个状态,第二个状态没有关闭。如果我处于次要状态,我想先关闭它。

这是我皮肤的代码class:

<?xml version="1.0" encoding="utf-8"?>
<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">

    <fx:Script>
        <![CDATA[
            protected function imageViewButton_clickHandler(event:MouseEvent):void
            {

                if (currentState==NORMAL_VIEW) {
                    currentState = IMAGE_VIEW;
                }
                else {
                    currentState = NORMAL_VIEW;
                }
            }

            protected function linkViewButton_clickHandler(event:MouseEvent):void
            {
                if (currentState==NORMAL_VIEW) {
                    currentState = LINK_VIEW;
                }
                else {
                    currentState = NORMAL_VIEW;
                }
            }

            public static var NORMAL_VIEW:String = "normal";
            public static var LINK_VIEW:String = "linkView";
            public static var IMAGE_VIEW:String = "imageView";
        ]]>
    </fx:Script>


    <s:transitions>
        <s:Transition fromState="normal" toState="*">
            <s:Sequence duration="250">
                <s:Resize target="{this}"/>
                <s:AddAction target="{linkViewButton}"/>
                <s:Fade target="{linkViewButton}"/>
            </s:Sequence>
        </s:Transition>

        <s:Transition fromState="linkView" toState="*">
            <s:Sequence duration="250">
                <s:Fade target="{linkViewButton}"/>
                <s:Resize target="{this}"/>
            </s:Sequence>
        </s:Transition>

        <s:Transition fromState="imageView" toState="*">
            <s:Sequence duration="250">
                <s:Fade target="{imageViewButton}"/>
                <s:Resize target="{this}"/>
            </s:Sequence>
        </s:Transition>
    </s:transitions>

    <s:states>
        <s:State name="normal"/>
        <s:State name="linkView"/>
        <s:State name="imageView"/>
    </s:states>


    <s:VGroup width="100%">
        <s:HGroup width="100%" >    
            <s:Button label="Button 1" />
            <s:Line height="100%">
                <s:stroke>
                    <s:SolidColorStroke color="#B3C2B8"/>
                </s:stroke>
            </s:Line>
            <s:ToggleButton id="gotoLinkView" label="Link Details" click="linkViewButton_clickHandler(event)"/>
            <s:Line height="100%">
                <s:stroke>
                    <s:SolidColorStroke color="#B3C2B8"/>
                </s:stroke>
            </s:Line>
            <s:ToggleButton id="gotoImageView" label="Image Details" click="imageViewButton_clickHandler(event)"/>
            <s:Line height="100%">
                <s:stroke>
                    <s:SolidColorStroke color="#B3C2B8"/>
                </s:stroke>
            </s:Line>
        </s:HGroup>

        <s:Button id="linkViewButton" label="Link View"
                  includeIn="linkView" 
                  itemCreationPolicy="immediate" width="100%"/>

        <s:Button id="imageViewButton" label="Image View"
                  includeIn="imageView" 
                  itemCreationPolicy="immediate"
                  width="100%"/>
    </s:VGroup>
</s:WindowedApplication>

检测到一个简单的逻辑错误。您的代码应该知道所有按钮(如果 pressed/released 有效,则更改它们的状态),或者使每个按钮只知道自己的状态而不受其他代码的影响。按照你的方法,我说你应该做第二个变体。

        protected function imageViewButton_clickHandler(event:MouseEvent):void
        {

            if (currentState!=IMAGE_VIEW) {
                currentState = IMAGE_VIEW;
            }
            else {
                currentState = NORMAL_VIEW;
            }
        }

        protected function linkViewButton_clickHandler(event:MouseEvent):void
        {
            if (currentState!=LINK_VIEW) {
                currentState = LINK_VIEW;
            }
            else {
                currentState = NORMAL_VIEW;
            }
        }

您不应该假设您的 "skin" 处于 NORMAL_VIEW 状态,而是检查每个按钮的所需状态,如果不存在则更改为所需状态,然后更改为预定义的正常状态(可以是如果您需要,每个按钮都不同,但最好保持正常)如果已经处于所需状态。

这是在多个状态之间转换的完整示例,其中可能存在打开状态,并且您希望在转换到另一个打开状态之前保留转换动画或将它们从打开状态中反转出来。感谢@Vesper 发现逻辑错误。

<?xml version="1.0" encoding="utf-8"?>
<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"
                       applicationComplete="windowedapplication1_applicationCompleteHandler(event)"
                       stateChangeComplete="windowedapplication1_stateChangeCompleteHandler(event)">

    <fx:Script>
        <![CDATA[
            import mx.events.FlexEvent;

            public static var NORMAL_VIEW:String = "normal";
            public static var LINK_VIEW:String = "linkView";
            public static var IMAGE_VIEW:String = "imageView";

            public var deferredState:String;
            public var deferredToggle:Object;

            protected function linkViewButton_clickHandler(event:MouseEvent):void
            {
                if (currentState!=LINK_VIEW) {
                    if (currentState != NORMAL_VIEW) {
                        deferredState = LINK_VIEW;
                        currentState = NORMAL_VIEW;
                        deferredToggle = event.currentTarget;
                        deselectToggles(deferredToggle);
                        return;
                    }

                    currentState = LINK_VIEW;
                }
                else {
                    currentState = NORMAL_VIEW;
                }
            }

            protected function imageViewButton_clickHandler(event:MouseEvent):void
            {

                if (currentState!=IMAGE_VIEW) {
                    if (currentState != NORMAL_VIEW) {
                        deferredState = IMAGE_VIEW;
                        currentState = NORMAL_VIEW;
                        deferredToggle = event.currentTarget;
                        deselectToggles(deferredToggle);
                        return;
                    }

                    currentState = IMAGE_VIEW;
                }
                else {
                    currentState = NORMAL_VIEW;
                }
            }

            protected function windowedapplication1_stateChangeCompleteHandler(event:FlexEvent):void
            {
                //trace("State change complete");

                if (currentState==NORMAL_VIEW) {
                    //trace("Normal state");
                }

                if (deferredState!=null) {
                    currentState = deferredState;
                    deferredState = null;
                    deferredToggle = null;
                }
            }

            public function deselectToggles(selectedToggle:Object=null):void {
                var toggle:ToggleButton;

                for (var i:int = 0; i < toggles.length; i++) 
                {
                    toggle = toggles[i] as ToggleButton;

                    if (toggle!=selectedToggle) {
                        toggle.selected = false;
                    }
                }

            }

            protected function windowedapplication1_applicationCompleteHandler(event:FlexEvent):void
            {
                toggles.push(gotoLinkView, gotoImageView);
            }

            public var toggles:Array = [];
        ]]>
    </fx:Script>


    <s:transitions>
        <s:Transition fromState="normal" toState="linkView" interruptionBehavior="stop" autoReverse="true">
            <s:Sequence duration="250" 
                        effectStart="trace('normal to link view')"
                        >
                <s:Resize target="{borderContainer}"/>
                <s:AddAction target="{linkViewButton}"/>
                <s:Fade target="{linkViewButton}"/>
            </s:Sequence>
        </s:Transition>

        <s:Transition fromState="normal" toState="imageView" interruptionBehavior="stop" autoReverse="true">
            <s:Sequence duration="250" 
                        effectStart="trace('normal to image view')"
                        >
                <s:Resize target="{borderContainer}"/>
                <s:AddAction target="{imageViewButton}"/>
                <s:Fade target="{imageViewButton}"/>
            </s:Sequence>
        </s:Transition>

    </s:transitions>

    <s:states>
        <s:State name="normal"/>
        <s:State name="linkView"/>
        <s:State name="imageView"/>
    </s:states>


    <s:BorderContainer width="100%" id="borderContainer">
        <s:layout>
            <s:VerticalLayout/>
        </s:layout>
        <s:HGroup width="100%" >    
            <s:Button label="Button 1" />
            <s:Line height="100%">
                <s:stroke>
                    <s:SolidColorStroke color="#B3C2B8"/>
                </s:stroke>
            </s:Line>
            <s:ToggleButton id="gotoLinkView" label="Link Details" click="linkViewButton_clickHandler(event)"/>
            <s:Line height="100%">
                <s:stroke>
                    <s:SolidColorStroke color="#B3C2B8"/>
                </s:stroke>
            </s:Line>
            <s:ToggleButton id="gotoImageView" label="Image Details" click="imageViewButton_clickHandler(event)"/>
            <s:Line height="100%">
                <s:stroke>
                    <s:SolidColorStroke color="#B3C2B8"/>
                </s:stroke>
            </s:Line>
        </s:HGroup>

        <s:Button id="linkViewButton" 
                  label="Link View" 
                  height="100"
                  includeIn="linkView" 
                  itemCreationPolicy="immediate" width="100%"/>

        <s:Button id="imageViewButton" 
                  height="100"
                  label="Image View"
                  includeIn="imageView" 
                  itemCreationPolicy="immediate"
                  width="100%"/>
    </s:BorderContainer>
</s:WindowedApplication>