什麼是狀態(States)?
在很多富互聯網應用,網頁外觀的改變基於用戶的行爲。一個狀態就定義了組件的一種表現樣式。要想使用狀態,你應該首先定義一個默認的狀態,然後在此基礎上重寫或者更改,這樣就形成了一系列的其他樣式。你可以添加、移除某些子元素,更改CSS或者屬性的值,更改觸發的事件。這些如何做到,我們會一一介紹。
下面我們先通過一個例子大概看一下如何使用State。
下面這段代碼呈現的首先是一個登陸的界面,當你單擊註冊的鏈接,它就會變成一個註冊界面。它是新的界面但不是新的頁面。通過瀏覽器的後退按鈕你是回不到原來的狀態的。當然,我們也會有辦法實現這個功能,以後會介紹。
<s:Application
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/halo" minWidth="1024"
minHeight="768">
<s:layout>
<s:BasicLayout/>
</s:layout>
<s:states>
<s:State
name="default"/>
<s:State
name="Register"/>
</s:states>
<!-- Set title of the Panel container based on the
view state.-->
<s:Panel id="loginPanel"
title="Login"
title.Register="Register">
<s:layout>
<s:VerticalLayout/>
</s:layout>
<mx:Form
id="loginForm">
<mx:FormItem
label="Username:">
<s:TextInput/>
</mx:FormItem>
<mx:FormItem
label="Password:">
<s:TextInput/>
</mx:FormItem>
<mx:FormItem id="confirm" label="Confirm:"
includeIn="Register">
<!-- Add a TextInput control to the form for the
Register view state. -->
<s:TextInput/>
</mx:FormItem>
<mx:FormItem
direction="horizontal">
<!-- Use the LinkButton to change view
state.-->
<mx:Spacer width="100%"
id="spacer1"/>
<!-- Set label of the control based on the view
state.-->
<mx:LinkButton id="registerLink"
label="Need to Register?"
label.Register="Return to Login"
click="currentState='Register'"
click.Register="currentState=''"/>
<s:Button id="loginButton"
label="Login"
label.Register="Register"/>
</mx:FormItem>
</mx:Form>
</s:Panel>
</s:Application>
定義狀態
flex4裏狀態的定義與flex3不同,你只需在<states></states>標籤內定義狀態就可以了。添加子元素和設置屬性之類,不在這裏進行了。如下所示:
<s:State name="State1"/>
<s:State name="State2"/>
<s:State name="State3"/>
.
.
</s:states>
改變狀態
UIComponent類定義了一個currentState屬性,通過改變這個屬性的值來更換狀態,這個屬性的默認值是定義在需在<states></states>標籤內的第一個狀態。例如:
<s:Button id="b2" label="Change to the default" click="currentState='State1';"/>
爲一個狀態設定屬性,樣式和事件
這是與flex3很不同的地方。在flex4裏通過點語法來設定一個組件屬於某個狀態的屬性值。例如:
上述代碼也可以這樣寫:
<s:label>Default State</s:label>
<s:label.State2>new State</s:label.State2>
</s:Button>
click="ta1.text='hello';"
click.State1="ta1.text='goodbye'"/>
添加或移除組件
在flex4裏,添加或移除某個組件,直接在這組件的屬性裏搞定。組件多了兩個屬性,includeIn和excludeFrom。includeIn,表示這個組件要被添加到屬性值所指的狀態,excludeFrom,表示這個組件要從屬性值所指的狀態中刪除,includeIn和excludeFrom不能在同一個組件標籤裏出現,他們的值可以是多個狀態,之間用逗號隔開。例如:
<s:states>
<s:State name="default"/>
<s:State
name="addCheckBox"/>
<s:State
name="addTextInput"/>
<s:State
name="addCheckBoxandButton"/>
</s:states>
<s:CheckBox id="myCB" label="Checkbox"
includeIn="addCheckBox, addCheckBoxandButton"/>
<s:TextArea text="Exclude from
addTextInput"
excludeFrom="addTextInput"/>
更改一個組件的父元素
一個組件的父元素也能變,你信嗎?不過flex4真的做到了。用的就是這個<fx:Reparent>標籤。還是看段代碼吧!
<!-- states\NewStatesReparent.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/halo"
xmlns:s="library://ns.adobe.com/flex/spark">
<s:layout>
<s:VerticalLayout/>
</s:layout>
<s:states>
<s:State name="Parent1"/>
<s:State name="Parent2"/>
</s:states>
<s:HGroup>
<s:Panel id="Panel1"
height="100" width="100"
title="Panel 1">
<s:Button id="setCB" includeIn="Parent1"/>
</s:Panel>
<s:Panel id="Panel2"
height="100" width="100"
title="Panel 2">
<fx:Reparent target="setCB" includeIn="Parent2"/>
</s:Panel>
</s:HGroup>
<s:HGroup>
<s:Button label="Parent 1"
click="currentState='Parent1'"
enabled.Parent1="false"/>
<s:Button label="Parent 2"
click="currentState='Parent2'"
enabled.Parent2="false"/>
</s:HGroup>
</s:Application>
添加子元素時的控制
或許,你有這樣的疑問。我爲某個狀態添加了一個子元素,這個元素在原來的狀態是不存在的,至少,你看不見。那麼,這個子元素時是在程序一運行時就被創建了還是在切換狀態時才創建呢?
flex4的答案是在第一次換到需要這個子元素出現的狀態時,它被創建。這是默認的情況。但是,如果這個子元素的創建需要很長時間,那麼用戶肯定在切換狀態時感到延遲,這是不好的。所以,默認的情況,可以改。通過更改itemCreationPolicy,這是組件的一個屬性,它有兩個值:deferred,默認值,意思是在第一次需要這個組件出現時創建;
immediate,它是在程序一被啓動就會創建這個子元素。
一旦子元素被創建了,它就會一直存在了。
界面的改變不是僅僅只能通過State。通過導航器,如:Accordion,Tab Navigator,ViewStack containers你也能做到。到底用哪個,取決於你的應用需求以及用戶界面的設計。
創建狀態組
在flex4裏,可以給狀態分組,比如第一個狀態和第二個狀態是一組,第三個狀態和第四個狀態是一組等等。我們先看怎麼分組?
<s:State name="addCheckBox" stateGroups="Group1"/>
<s:State name="addTextInput"/>
<s:State name="addCheckBoxandButton" stateGroups="Group1"/>
添加分組的好處是什麼呢?
如果一個組件在多個狀態中出現,你就可以把這些狀態劃分到一組。那麼,當出現這個族裏任何一個狀態時,這個組件的設置都會有效。點語法後面的值可以是組的名稱,excludeFrom和includeIn的值也可以使組的名稱。