ApplicationControlBar组件对State的影响

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

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

 1ArgumentError: Error #2025: 提供的 DisplayObject 必须是调用者的子级。
 2	at flash.display::DisplayObjectContainer/removeChild()
 3	at mx.core::Container/removeChild()
 4	at mx.states::AddChild/remove()
 5	at mx.core::UIComponent/::removeState()
 6	at mx.core::UIComponent/::commitCurrentState()
 7	at mx.core::UIComponent/setCurrentState()
 8	at mx.core::UIComponent/set currentState()
 9	at stateTest2/::baseHandler()
10	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的影响 未修改前效果

请使用下面的链接升级 Flash Player 到最新版本:

安装最新的Flash Player插件

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

请使用下面的链接升级 Flash Player 到最新版本:

安装最新的Flash Player插件

源码(未修改前):

 1<?xml version="1.0" encoding="utf-8"?>
 2<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical">
 3	<mx:Script>
 4		<![CDATA[
 5			private function baseHandler():void
 6			{
 7				currentState = "";
 8			}
 9			private function state1Handler():void
10			{
11				currentState = "state1";
12			}
13			private function state2Handler():void
14			{
15				currentState = "state2";
16			}
17		]]>
18	</mx:Script>
19	<mx:Style>
20		Application
21		{
22			font-size:12;
23		}
24	</mx:Style>
25	<mx:states>
26		<mx:State name="state1">
27			<mx:AddChild position="lastChild">
28				<mx:ApplicationControlBar id="appBar" dock="true" width="100%">
29					<mx:Label text="state1 in ApplicationControlBar"/>
30				</mx:ApplicationControlBar>
31			</mx:AddChild>
32			<mx:RemoveChild target="{label1}"/>
33		</mx:State>
34		<mx:State name="state2">
35			<mx:AddChild position="lastChild">
36				<mx:Label text="state2"/>
37			</mx:AddChild>
38			<mx:RemoveChild target="{label1}"/>
39		</mx:State>
40	</mx:states>
41	<mx:HBox>
42		<mx:Button label="切换到baseState" click="baseHandler()"/>
43		<mx:Button label="切换到state1" click="state1Handler()"/>
44		<mx:Button label="切换到state2" click="state2Handler()"/>
45	</mx:HBox>
46	<mx:Label text="base state" id="label1"/>
47</mx:Application>