2007/04/27
Flexでコントロールのアタッチ/デタッチを実行時に楽に行う
Apolloをやるために、いまさらFlexを始めています。
ちょっとしたことにはいちいちカスタムコンポーネントを作らず、既存のコントロールとデータバインディングで何とかしたい。
じゃあこういう時はどうしましょう。メモその2です。
実行時の状況に応じてコントロールを表示したい場合。例えばビデオが停止しているときはplayボタンを、再生しているときはpauseボタンを表示したい。ボタンを一つだけ置いてラベルやハンドラを条件分岐する方法もあるのですが、できれば役割ごとに記述を分けたいですね。
そこで二つとも置いといて、必要なほうだけ表示するという手をとりました。
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical">
<mx:VideoDisplay id="video"
source="sample.flv" autoPlay="false" playheadUpdateInterval="30"/>
<mx:HBox>
<mx:Canvas>
<mx:Button label="Play" visible="{!video.playing}" width="100%" click="video.play();"/>
<mx:Button label="Pause" visible="{video.playing}" width="100%" click="video.pause();"/>
</mx:Canvas>
<mx:Button label="Stop" click="video.stop();"/>
</mx:HBox>
</mx:Application>
動作。
どっちを表示しても同じ幅で表示されるのが便利です。
では、「二つとも置いといて」が使えない場合はどうしたら良いでしょうか。例えば以下のようなXMLを元に、テキスト又は画像を並べて配置したい場合。
<test>
<text>Joe</text>
<text>Fred</text>
<image>sample.jpg</image>
<text>Sue</text>
</test>
先ほどと同じ方法だとこうなります。
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical" horizontalAlign="left">
<mx:XML id="test">
<test>
<text>Joe</text>
<text>Fred</text>
<image>sample.jpg</image>
<text>Sue</text>
</test>
</mx:XML>
<mx:Repeater id="testRepeater" dataProvider="{test.children()}">
<mx:Text text="{testRepeater.currentItem}"
visible="{XML(testRepeater.currentItem).localName()=='text'}"/>
<mx:Image source="{testRepeater.currentItem}"
visible="{XML(testRepeater.currentItem).localName()=='image'}"/>
</mx:Repeater>
</mx:Application>
表示されてない側のコントロールのせいでへんな隙間が開いてしまっています。これを抑制するためにCanvasで包んでも、Canvasのサイズ計算時に邪魔になりそうです。じゃあ非表示のコントロールのheightを0にして……。面倒ですし、今後コントロールの種類が増えたときに使わないものが多くなり無駄です。
実行時にコントロールをアタッチ/デタッチする方法はないのでしょうか。カスタムコンポーネントを作らずに。
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical" horizontalAlign="left">
<mx:XML id="test">
<test>
<text>Joe</text>
<text>Fred</text>
<image>sample.jpg</image>
<text>Sue</text>
</test>
</mx:XML>
<mx:Repeater id="testRepeater" dataProvider="{test.children()}">
<mx:Repeater dataProvider="[1]"
count="{XML(testRepeater.currentItem).localName()=='text'?1:0}">
<mx:Text text="{testRepeater.currentItem}"/>
</mx:Repeater>
<mx:Repeater dataProvider="[1]"
count="{XML(testRepeater.currentItem).localName()=='image'?1:0}">
<mx:Image source="{testRepeater.currentItem}"/>
</mx:Repeater>
</mx:Repeater>
</mx:Application>
そこでRepeaterを使ってみました。思い通りの動作になりましたが正直どうなんでしょう。
コメント一覧