statesプロパティを使って、UIの状態遷移を管理する
アプリケーションの状態に応じてUIを変化させたいという需要はなかなか多いような気がする。
僕はすぐにTabBarとViewStackを使ってしまうんだが、今回はUIComponentのプロパティであるstatesを使ってみようと思う。
サンプル
まずはstatesを使った簡単な例を
http://tsuyabu.in/~umezo/samples/flex/state/StateTest.swf
Main.mxml
<?xml version="1.0"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"> <mx:states> <mx:State name="FirstState"> <mx:RemoveChild target="{btn}"></mx:RemoveChild> <mx:AddChild relativeTo="{this}" position="lastChild"> <mx:target> <mx:Panel title="FirstState"> <mx:Button label="State" click="this.currentState = '' " /> </mx:Panel> </mx:target> </mx:AddChild> </mx:State> </mx:states> <mx:Button id="btn" label="FirstState" click="this.currentState = 'FirstState'" /> </mx:Application>
ボタンをクリックする毎に初期状態とFirstStateという状態を行ったり来たりするという物になっている。
ほとんどASを書かなくても、UIを変化させられるところが特徴。
次に状態をどのように定義しているのかを見ていく。
初期状態の定義
初期状態の定義は簡単で
上の例で言うとこの部分になる。
<mx:Button id="btn" label="FirstStateへ" click="this.currentState = 'FirstState'" />
つまり、このmxmlの初期状態はボタンが1つだけ配置されている状態となる。
他の状態の定義
初期状態以外の定義はstatesプロパティの中にStateタグを記述していくことで定義できる。
状態は複数定義することも出来る。
このときStateのnameプロパティを任意の名前に設定しておくことで、状態遷移を起こすことが出来る。
というわけで、必ずnameプロパティを設定しておこう。
記述例
<mx:states> <mx:State name="FirstState"> ... </mx:State> <mx:State name="SecondState"> ... </mx:State> <mx:State name="ThirdState"> ... </mx:State> </mx:states>
状態を遷移させる
さて定義した状態間を遷移するためにはUIComponentのcurrentStateプロパティに状態の名前を代入する。
たとえば以下のように書くと、現在の状態からFirstStateという状態に遷移する。
this.currentState = "FirstState";
初期状態を含めた4つの状態を遷移するサンプル
http://tsuyabu.in/~umezo/samples/flex/state/StateTest2.swf
Main.xml
<?xml version="1.0"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"> <mx:states> <mx:State name="FirstState"> <mx:AddChild relativeTo="{this}" position="lastChild"> <mx:target> <mx:Panel title="FirstState"> <mx:Button label="to Default State" click="this.currentState = '' " /> </mx:Panel> </mx:target> </mx:AddChild> </mx:State> <mx:State name="SecondState"> <mx:AddChild relativeTo="{this}" position="lastChild"> <mx:target> <mx:TextArea text="Second State"/> </mx:target> </mx:AddChild> </mx:State> <mx:State name="ThirdState"> <mx:AddChild relativeTo="{this}" position="lastChild"> <mx:target> <mx:TitleWindow title="Third State"></mx:TitleWindow> </mx:target> </mx:AddChild> </mx:State> </mx:states> <mx:Button label="to Default State" click="this.currentState = ''" /> <mx:Button label="to First State" click="this.currentState = 'FirstState'" /> <mx:Button label="to Second State" click="this.currentState = 'SecondState'" /> <mx:Button label="to Third State" click="this.currentState = 'ThirdState'" /> </mx:Application>
最後にStateタグの中身に何を書いたらいいのか見ておこう。
Stateの中身
Stateの中身には、"初期状態からどのように変化したらその状態になるのか"を書く。
#正確にはこの表現は嘘で、初期状態以外からの遷移も定義することが出来る。が、今回はふれない。
自分で言っていて意味不明である。
初っぱなの例を参考にしよう。
<mx:RemoveChild target="{btn}"></mx:RemoveChild> <mx:AddChild relativeTo="{this}" position="lastChild"> <mx:target> <mx:Panel title="FirstState"> <mx:Button label="State" click="this.currentState = '' " /> </mx:Panel> </mx:target> </mx:AddChild>
この部分がStateの中身になる。
まず、コレの意味を説明すると、
- 初期状態からbtnを取り除く
- thisの一番最後にmx:target以下のコンポーネントを追加する
という意味になっている。
と、このように、初期状態からいらない物をRemoveChildタグで定義し、新たに追加するものとAddChildタグに定義することで、状態遷移を定義する。
Stateタグの中で使える物には以下のようなものもある
- mx.states.AddChild
- mx.states.RemoveChild
- mx.states.SetEventHandler
- mx.states.SetProperty
- mx.states.SetStyle
注意
currentStateには一つしか状態を設定できない
まぁ当たり前と言えば当たり前なんだが、後読みでデータがそろった順にコンポーネントを表示したい時なんかはStateで管理しずらい。
#どのコンポーネントから準備が整うかわからないため、中間の状態が一意に定義出来ない。
複雑な状態遷移の場合はあらかじめ設計を考える
states要素はmxmlのルート要素にしか定義できない。
このため、子供のコンポーネントのstatesを設定したい場合は、必ず別ファイルに定義することになる。
こうなってくると、はじめから計画的に、状態を設計しておく必要が出てくる。
#別ファイルにするとidプロパティでのアクセスが出来なくなるので、eventを定義するなどしなければならなくなる。
まとめ
statesプロパティを使うとUIの状態遷移を管理出来る。
一方で複雑な状態を管理するには、それなりの準備が必要になる。
簡単な状態遷移の場合は率先して使っても良いかも。
今回説明していないがTransitionが使えるようになることが、最大のメリットな気がする。
Transitionについては後日、書きます。