[原文出处: http://swfever.com/?p=717]
本章我们将介绍Flex 4中其他与视图状态相关的新特性和变化,包括:
在上一章登录/注册对话框的例子中,当我们将视图状态切换到register时,会需要创建一个额外的Label组件和TextInput组件作为密码确认的输入框,当切换回login状态时,这些组件又将不再显示。这就引发了两个问题:
事实上,这两个问题的答案都取决于开发者的需求。如果我们选择初始化阶段创建所有组件,那么在状态切换时,你会获得更短的响应时间,但是会增加不必要的内存占用。如果你选择只在需要时创建组件并在不需要时将其销毁,那么内存占用会更加合理,但是相应地,你需要更多的响应时间来完成创建和销毁组件的工作。
无论如何,Flex 4提供了非常简便的方式来满足你的需求:
控制组件的创建时机 - itemCreationPolicy属性
控制组件的销毁时机 - itemDestructionPolicy属性
可以看到,Flex 4默认的处理方式为:直到组件被需要时(切换到指定状态)才被创建,但一旦被创建后就不会被销毁。你可以根据自己的需要来改变创建和销毁的机制,例如:
<s:states> <s:State name="login"/> <s:State name="register"/> </s:states> <s:Panel> <s:TextInput id="confirmInput" includeIn="register" itemCreationPolicy="immediate" itemDestructionPolicy="auto" /> </s:Panel>
在上面的例子中,尽管默认状态为login,但是confirmInput仍然会在整个MXML组件构造初期就被创建,但是当从login状态切换至register在切换回login状态时,confirmInput所引用的对象将会被销毁。如果再次切换至register状态,一个新的TextInput组件会被创建,但是confirmInput将始终为null。
需要注意的是,itemCreationPolicy,itemDestructionPolicy以及上一章中介绍的includeIn和excludeFrom,都是MXML特有属性(即XML Attributes),和组件属性(Properties)不同。只有当你使用MXML 2009时,才能够使用这些属性。
状态组是一个非常有用的新特性。当组件定义的状态比较多的时候,我们可能希望将针对某几种状态做统一的设置。例如,ToggleButton组件定义了如下状态:
我们可能会经常有这样的需求:“对于所有的over状态(over或overAndSelected),我希望按钮标签颜色为红色”,或者“对于所有selected状态,我希望按钮的字体为粗体”。可以想象,满足这样的需求需要很繁复的工作,你不得不为每一个selected有关的状态设置粗体或者为每一个与over有关的状态设置颜色。但是,有了状态组的支持,你可以各种状态按照你的需求自由的组织起来。
状态组的基本原则是:一个状态组可以包含多个状态,一个状态可以隶属于多个状态组。也就是说,这是一个多对多的映射,你可以根据需要随意组织。例如,为了满足上面提到的两个需求,我们可以将ToggleButton的状态用两个状态组组织起来:
<s:states> <s:State name="up" /> <s:State name="over" stateGroups="overStates" /> <s:State name="down" /> <s:State name="disabled"/> <s:State name="upAndSelected" stateGroups="selectedStates" /> <s:State name="overAndSelected" stateGroups="selectedStates, overStates" /> <s:State name="downAndSelected" stateGroups="selectedStates" /> <s:State name="disabledAndSelected" stateGroups="selectedStates" /> </s:states>
可以看到,我们一共定义了两个状态组:overStates和selectedStates。前者包含了所有与over有关的状态,而后者则包含了所有与selected有关的状态。接下来的事情就变得简单了,我可以通过下面的语句来设置按钮标签的颜色和字体:
<s:Label id="label" color.overStates="Red" fontWeight.selectedStates="bold" />
在Flex 4 (MXML 2009)中,我们取消了原有的默认状态“Base State”,起始状态默认情况下为第一个被显式定义的状态。这一点也可以从Flash Builder的设计视图中看到:
Reparent标签必须和includeIn或excludeFrom一起使用。它相当于一个占位符,当切换到包含该标签的状态时,Reparent标签的位置会被其指定的目标对象(target)所代替,从而达到对组件在特定状态下重新定位的效果。例如:
<s:states> <s:State name="state1" /> <s:State name="state2" /> </s:states> <s:Group id="group1"> <s:Button id="button" includeIn="state1" /> </s:Group> <s:Group id="group2" x="200"> <fx:Reparent target="button" includeIn="state2"/> </s:Group>
在上面的例子中,当状态从state1切换到state2时,button组件会从group1中移除,并被添加到的group2中。
虽然标签的名字叫做“Re-parent”,但是并不意味着该标签必须出现在与目标组件不同的父级中,你也可以在与目标相同的父级容器中使用该标签,例如:
<s:states> <s:State name="state1" /> <s:State name="state2" /> </s:states> <s:Group> <s:Button id="button1" includeIn="state1" /> <s:Button id="button2"/> <fx:Reparent target="button1" includeIn="state2"/> </s:Group>
在上面例子中,当状态切换到state2时,button1和button2的遮盖顺序会颠倒过来。你可以发挥你的想象力去挖掘这个标签的潜在用途。