今回取り上げるコンポーネント

  1. コンボボックス【ComboBox】

本記事中のサンプルを表示するには最新のFlashPlayer9が必要です(本稿執筆時点では【9,0,28,0】が最新)。こちらから最新のFlashPlayer9をインストールしてください。また,インストール後はブラウザの再起動が必要です。インストールされているFlash Playerのバージョンを確認するにはこちら

 今回も引き続き,Flexが備えるMXMLコンポーネントを紹介していきます。今回はコンボボックス【ComboBox】コンポーネントです。前回のList同様にHTMLでは「SELECT」タグで表現できますが,FlexのComboBoxはHTML以上のことが可能です。

コンボボックス【ComboBox】

 ComboBoxコンポーネント*1は複数のコンポーネントで構成される,複合コンポーネントです。例えば,ComboBoxの右側のボタンをクリックしたときに表示される,「ドロップダウンリスト」はデフォルトでは前回紹介したListコンポーネント*2です。

 Listは前回紹介したように複数の高度なコンポーネントを多重継承していますが,ComboBoxはそれらの高度なコンポーネントを内部的に使用しています。また,Listと同様にComboBoxにもベースとなる親クラスが存在します。その親クラスはComboBaseクラスです*3

 では,実際にサンプルを見てみましょう(図1)。

図1●【List】サンプル
図1●【ComboBox】サンプル(クリックすると別ウィンドウで表示します。ソースはこちら

 上から順に
1-1.ノーマル状態
1-2.オンコーディングでString型データをセット
1-3.オンコーディングでObject型データをセット
1-4.「1-3」と同様にObject型のデータですがデータ構造が少し違う
1-5.バインディング機能を利用してデータをセット
1-6.ドロップダウンリストの表示文字列をユーザー定義関数で作成
1-7.入力可能なコンボボックス
1-8.ドロップダウンリストの幅を指定
1-9.ドロップダウンリストの表示行数を指定
1-10.選択されているデータを知る
1-11.行内にイメージを表示
1-12.データを動的に生成してイメージも表示させる
1-13.ドロップダウンリストの開閉操作
1-14.ドロップダウンリストの開閉速度
1-15.ドロップダウンリストの開閉アニメーション
1-16.各イベントの発生タイミング
1-17.ドロップダウンリストにTileListを使用する
1-18.ComboBoxからListへドラッグ&ドロップ

となります。

 1-1.は,「width」属性を指定しただけでリストデータも無い状態です。この状態でComboBoxをクリックすると,1行分だけの何も無い空のドロップダウンリストが表示されます。

 1-2.は,オンコーディングでString型のArrayを「dataProvider」属性にセットしています。ドロップダウンリストの選択アイテムを変更すると選択した文字列データがTextAreaに出力されます。

 1-3.は,ComboBox自体の属性値は「1-2」と同じです。ただ,「dataProvider」属性にセットしているのがObject型のArrayです。ComboBoxに表示されるのはObjectの「label」属性で,TextAreaに表示される「ComboBox.value」の値はObjectの「data」属性です。これはオブジェクトの配列が「dataProvider」属性にセットされたときのデフォルトの仕様になります。

 1-4.は,「1-3」と同じようにObject型のArrayを「dataProvider」属性にセットしていますが,Object型の構造が若干違います。Object型に「name」属性が追加されています。ドロップダウンリストに表示されているのは「labelField」属性で指定したObject型の属性です。

 1-5.は,「1-3」とほぼ同じですが,第8回で紹介したバインディング機能を利用してComboBoxの「dataProvider」属性に「_cmbData1」変数を連動させています。

 上記のサンプルについて第9回のListのサンプルソースと比較していただくとわかりますが,「1-1」から「1-5」は第9回と全く同じコーディングです。「mx:List」が「mx:ComboBox」に変わったぐらいです。これはComboBoxの「dataProvider」属性に指定したデータがデフォルトのドロップダウンリストであるListにそのまま使用されるからです。

 1-6.を見ると,「選択してください」とComboBoxには表示されています。これはドロップダウンリストのデータの先頭行に「選択してください」という文字列を付加したのではありません。ComboBoxの「prompt」属性に指定した文字列が表示されるようになっています。何かしらリストからアイテムを選択すると「prompt」属性はクリアされます。

 この「prompt」属性が表示されている状態における「selectedIndex」(ドロップダウンリストで選択されてインデックス)は「-1」です。つまり,何も選択されていない状態を意味します。また,「labelFunction」属性を指定しています。これはドロップダウンリストに表示する文字列をカスタマイズするユーザー定義関数を指定するための属性です*4。サンプルでは「labelDataFunction」関数でObject型の「name」属性と「data」属性を連結して表示しています。

 1-7.は,入力が可能なComboBoxで,「prompt」属性も指定しています。まず,入力を受け付けるようにするためには「editable」属性を「true」にします。また,「restrict」属性で「0-9」と指定しているので数値しか入力できません。入力エリアで「Enter」キーが押されたタイミングを「enter」イベントで検知しています。サンプルでは「enterKeyHandler」関数(図2)と連携させています。

図2●「enterKeyHandler」関数
図2●「enterKeyHandler」関数

 ActionScriptを簡単に説明すると,「e.currentTarget」のクラスを「is」演算子で検証しています(別に無くても良いのですが)。「ComboBox」でない場合は関数をすぐに抜けるようになっています。次に,実装時は単純なObject型である「e.currentTarget」を型キャストでComboBoxクラスの変数に代入しています(※新しいインスタンスが生成されるわけではありません)。

 さらに実装時は,単純なObject型である「ComboBox.dataProvider」は,このサンプルでは実行時に「ArrayCollection」クラスになっているので「source」属性からArrayを取り出します(※新たにインスタンスを生成するのではありません)。そして入力された内容を配列に追加しています。これでComboBoxに入力された文字列が追加されます。

 入力エリアにフォーカスを当てたときには,「入力できます」が消えてすぐに入力できるとありがたいと思いますが,「prompt」属性をセットしたからと言ってそこまではしてくれません。なので,自前でフォーカスを取得したという「focusIn」イベントを検知し,「prompt」の内容をクリアしています。

 1-8.は,「dropdownWidth」属性でComboBoxの幅とは別にドロップダウンリストの幅を指定しています。ComboBoxをクリックしてドロップダウンリストを表示すると,ComboBoxよりもドロップダウンリストのほうが長いのがわかると思います。

 1-9.は,「rowCount」属性でドロップダウンリストの表示行数を指定しています。また,ComboBoxの「creationComplete」イベントで100件のデータを生成してComboBoxにセットしています。

 1-10.は,「1-9」と同様に「creationComplete」イベントでデータを生成しています。ただし,生成しているデータは若干複雑でArrayの各要素にObject型をセットし,さらにそのObject型の中にArrayを生成し階層構造化しています。ドロップダウンリストに表示されているのは階層構造の一番上のObject型の「label」属性ですが,ちゃんとデータの階層構造は生きています。「データチェック」ボタンを押すと選択されているアイテムのデータ構造がTextAreaに出力され確認することができます。

 1-11.は,オンコーディングでイメージを含むデータ構造を「dataProvider」属性にセットしています。

 1-12.は,動的にイメージを含むデータ構造を作成し「dataProvider」属性にセットしています。

 これらの「1-11」と「1-12」は第9回のListで行ったことと全く同じことをしています。実装コードの詳しくは第9回を参照してください。

 1-13.は,ComboBoxの「open」メソッドでドロップダウンリストを開き,「close」メソッドでドロップダウンリストを閉じています。このようにActionScriptで開閉操作を行うことも可能だということを知っておいてください。

 1-14.は,「openDuration」スタイルで開く速度を,「closeDuration」スタイルで閉じる速度を指定しています。指定する値はミリ秒(1秒=1000ミリ秒)です。デフォルトはどちらも250ミリ秒です。注意点は「属性」ではなく「スタイル」ということです。MXMLではどちらも同じ書き方で実現できますがActionScriptでスタイルを指定するときはsetStyleメソッドを使用する必要があります。

 1-15.は,ドロップダウンリストの開閉に様々なアニメーション効果を適用したサンプルです。ここで使用したアニメーション効果は「イージング」というものです。オーサリングソフトのFlash8のヘルプから引用すると

"イージング" とは,アニメーションの中で動きを徐々に加速または減速することを意味し,アニメーションをよりリアルに見せるために役立ちます。

 「アニメーション時間」の値を変更するとアニメーションの実行時間が変化します。いろいろ値を変えてお試しください。アニメーションに関する解説は省略させていただきますので,日本語のオンラインヘルプ「イージング関数の使用」や「パッケージ mx.effects.easing」をご参照ください。

 1-16.では,ComboBox特有のイベントの発生タイミングがわかるようにTextAreaに出力しています。「change」イベントは選択アイテムが変化したとき,「open」イベントはドロップダウンリストが表示されたとき,「close」イベントはドロップダウンリストが閉じたとき,「itemRollOver」イベントはドロップダウンリストのアイテムにマウスが合わさったとき,「itemRollOut」イベントはドロップダウンリストのアイテムからマウスが離れたときに発生します。試してみてください。

 1-17.は,ドロップダウンリストとして,TileListコンポーネント*5が使用されます。これは「dropdownFactory」属性に,ドロップダウンリストとして利用するクラスとして「mx.controls.TileList」を指定しているからです。注意点としてはどんなクラスでも「dropdownFactory」属性に指定できるわけではありません。ComboBoxのドロップダウンリスト用参照変数である「dropdown」属性の型はListBaseクラス*6です。したがって,ドロップダウンリストにはListBaseクラスを継承しているクラスを使用する必要があります。「dropdownFactory」属性に別のクラスを割り当てると,ドロップダウンリストの表示方法が変わるだけでComboBoxとしての機能はそのままです。

 1-18.は,ComboBoxからアイテムを選択&ドラッグし,Listにドロップするサンプルです。実際に試してみてください。サンプルのソースを見ると非常に簡単に実装できていますが,少々"癖"があります。まず,List側にドロップするには「dropEnabled」属性を「true」にする必要があります。そして,ComboBox側でドラッグを可能にするためにComboBox自体には手を加えません。

 設定が必要なのはComboBoxで表示されるドロップダウンリストです。ここにComboBoxの"癖"があります。「ComboBox.dropdown」にドラッグを可能にする設定をすれば良いわけですが,「ComboBox.dropdown」はComboBoxが閉じるたびに破棄されます。つまり,開くときにまた作成されるわけです。

 ComboBoxのソースを追っても明確にそのタイミングがわからなかったのですが,ComboBoxの「open」イベントで「ComboBox.dropdown」の参照値をデバッグしてみたところ毎回値が変わっていました。したがって,ドラッグを可能にする設定をするには「open」イベント毎に設定をする必要があります。これをComboBoxの「creationComplete」イベントで設定すると"最初の一回"はドラッグ&ドロップが可能なのですが,一度でもComboBoxが閉じてしまうとドラッグ&ドロップができなくなりますので注意してください。

 ComboBox側の設定は「ComboBox.dropdown.dragEnabled」を「true」,「ComboBox.dropdown.dragMoveEnabled」を「false」にします(「ComboBox.dropdown.dragMoveEnabled」を「true」にするとドラッグしたアイテムがListに移動します)。また,ドラッグ&ドロップが完了してもComboBoxのドロップダウンリストは開きっぱなしです。サンプルではドロップされたイベント(DragEvent.DRAG_COMPLETE)を検知してComboBoxを閉じるようにするために,「addEventListener」メソッドを使用して「DragEvent.DRAG_COMPLETE」イベントに「ComboBox.close」メソッドをで割り当てています。これでドラッグ&ドロップ完了時に「ComboBox.close」メソッドが実行されます。

  【修正履歴】図2を差し替えました。また,「1-3.は,List自体の属性値は…」とあったのを,「1-3.は,ComboBox自体の属性値は…」に修正しました。(2007年3月7日)