ApplicationControlBar组件对State的影响

  • 本站文章除注明转载外,均为本站原创或者翻译。
  • 本站文章欢迎各种形式的转载,但请18岁以上的转载者注明文章出处,尊重我的劳动,也尊重你的智商;
  • 本站部分原创和翻译文章提供markdown格式源码,欢迎使用文章源码进行转载;
  • 本博客采用 WPCMD 维护;
  • 本文标题:ApplicationControlBar组件对State的影响
  • 本文链接:http://zengrong.net/post/339.htm

碰到这样一个奇怪的问题:

一个Flex 2项目,其中算上Base state一共有三个state(以下简称baseState、state1、state2),从baseState到state2的互相切换都很正常,切换的state1也很正常。但是一旦切换到state1后,就不能再切换回state2或者baseState了,报错如下:

ArgumentError: Error #2025: 提供的 DisplayObject 必须是调用者的子级。
    at flash.display::DisplayObjectContainer/removeChild()
    at mx.core::Container/removeChild()
    at mx.states::AddChild/remove()
    at mx.core::UIComponent/::removeState()
    at mx.core::UIComponent/::commitCurrentState()
    at mx.core::UIComponent/setCurrentState()
    at mx.core::UIComponent/set currentState()
    at stateTest2/::baseHandler()
    at stateTest2/___Button1_click()

百思不得其解,进行了无数次测试后发现问出出在ApplicationControlBar组件上。

原来,在项目设计中,baseState是一个loading效果,state1则是主要界面内容。在state1中,有一个ApplicationControlBar组件,这个组件有一个dock属性。当dock属性值为true的时候,ApplicationControlBar会自动贴紧在界面上边缘,为了实现这个功能,或许Flex自动将ApplicationControlBar组件的层级提升至最高层。这样,当切换到其他state需要自动删除此组件的时候,由于组件处于最高层而不能被删除,就出现了上面的错误。

知道错误的原因,解决方法也就非常简单了:将dock属性设置为false或者直接删除dock属性即可。

也可以把ApplicationControlBar组件作为其他组件(例如VBox)的子级添加,然后通过操作其父组件来显示它。

如果是Debug版本的Flash Player,测试下面的Demo就可以看到出错信息:

ApplicationControlBar组件对State的影响 未修改前效果

ApplicationControlBar组件对State的影响 修改后效果

源码(未修改前):

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical">
    <mx:Script>
        <![CDATA[
            private function baseHandler():void
            {
                currentState = "";
            }
            private function state1Handler():void
            {
                currentState = "state1";
            }
            private function state2Handler():void
            {
                currentState = "state2";
            }
        ]]>
    </mx:Script>
    <mx:Style>
        Application
        {
            font-size:12;
        }
    </mx:Style>
    <mx:states>
        <mx:State name="state1">
            <mx:AddChild position="lastChild">
                <mx:ApplicationControlBar id="appBar" dock="true" width="100%">
                    <mx:Label text="state1 in ApplicationControlBar"/>
                </mx:ApplicationControlBar>
            </mx:AddChild>
            <mx:RemoveChild target="{label1}"/>
        </mx:State>
        <mx:State name="state2">
            <mx:AddChild position="lastChild">
                <mx:Label text="state2"/>
            </mx:AddChild>
            <mx:RemoveChild target="{label1}"/>
        </mx:State>
    </mx:states>
    <mx:HBox>
        <mx:Button label="切换到baseState" click="baseHandler()"/>
        <mx:Button label="切换到state1" click="state1Handler()"/>
        <mx:Button label="切换到state2" click="state2Handler()"/>
    </mx:HBox>
    <mx:Label text="base state" id="label1"/>
</mx:Application>