ComboBoxとCellRendererとListData

では引き続き行ってみましょう

 そういや、fl.controls.ComboBox途中だったなー、途中でDataProvider調べにいったもんだから。
 えーと、試験的に本文中のオブジェクト、メソッド、プロパティに色付けてみる。
 そういや、ソースコードに自動で色付けてくれるスクリプトをどっかで見たような気もする…Syntax Highlighterか、ふむ。次回あたり導入してみよう。とりあえず、今回のソースコードはプレーンで。
 なお、本家のドキュメントはComboBox の使用のあたりに書いてあるが、ほぼコンポーネントをステージに置くだけの浅い内容。

ComboBoxの背景を変える

 まずはドロップダウンリストのサンプルを作る。
成果:鳶嶋工房 / User Interface / Terms / ドロップダウンリスト

 あ、そうそうdataProviderにlabelが含まれてなくても、labelFieldプロパティにラベルに表示したい値を設定しておけばいい。
 デフォルトが"label"なだけで、絶対labelでなきゃいけないわけじゃない。

 labelFunctionを使えばフィルタ的なこともできる。複数の要素に含まれる文字列を結合したり。
 ん、labelの値によってラベルの文字や背景色を変える、なんてこともできそうな気がするな。
 ちょっとやってみるか。

 …えーと、表示しているラベルそれぞれはどうやったら指定できるんでしょうか?
 リファレンスを見ると、dropdownプロパティがドロップダウンのリストへの参照が入っているものらしい。
 おおっと、fl.controls.Listの使い方が分からないといけないじゃない。しばし、リファレンスを読む。
 あーリストの中にさらに、fl.controls.listClasses.CellRendererが入ってて、それをgetItemAt()メソッドで取り出せると…うむgetItemAt()メソッドで取り出せるのはデータの方でオブジェクトの参照じゃないみたいだ。しばし、リファレンスを読む。
 さらにCellRendererの中にflash.text.TextFieldが入ってて、こいつにTextFormatを設定してって…おやがめこがめまごがめだねぇ。凄いや。
 で、どうやったらCellRendererオブジェクトの参照が取れるの???

 交互に背景色を変えつつ、都道府県それぞれで文字の色が変わるドロップダウンリストでも作ってみるか。
 …2時間経過、うわっ全然わかんねぇ。やべぇ。
 Adobe本家のFiltering and formatting data in the DataGrid component | Adobe Developer Connectionあたりの記事がそれっぽい気がする。えーと、背景変えるのにCellRendererをカスタマイズする必要があるのかっ! なんとも隔靴掻痒な感じだっ。
 ともかく、やってみる。

 どうも記事は当たりだったみたいで、真ん中あたりの「Alternating background colors in a data grid」ってとこが、シマシマ背景を作るところっぽい。
 しばらく試行錯誤の後、なんとかできた。
 AlternatingRowColors.asは丸っきり記事のまま利用。んでflaのライブラリにComponent Assets/CellRendererSkins/CellRenderer_upSkinってのがあるのでこれを複製して、プロパティの[ActionScriptに書き出し]にチェックを入れて、クラス名がCellRenderer_upSkinGrayのやつとCellRenderer_upSkinDarkGrayの二つを作る。
 これで準備完了。

 クラスをスタイルシートとして設定するのが、ちょっと妙な感じもする。他のクラス(例えばfl.controls.dataGridClasses.DataGridColumn)にはcellRendererってプロパティが存在してたりもして、それもまた気持ち悪い。

import fl.data.DataProvider;
import fl.controls.List;
import AlternatingRowColors;

const PREFECTURES:Array = ["北海道","青森県","岩手県","宮城県","秋田県","山形県","福島県","茨城県","栃木県","群馬県","埼玉県","千葉県","東京都","神奈川県","新潟県","富山県","石川県","福井県","山梨県","長野県","岐阜県","静岡県","愛知県","三重県","滋賀県","京都府","大阪府","兵庫県","奈良県","和歌山県","鳥取県","島根県","岡山県","広島県","山口県","徳島県","香川県","愛媛県","高知県","福岡県","佐賀県","長崎県","熊本県","大分県","宮崎県","鹿児島県","沖縄県" ];
var dp:DataProvider = new DataProvider();

for ( var i:uint = 0; i < 47; i++ )
{
	dp.addItem( { label:( PREFECTURES[ i ] ), data:i + 1 } ); 
}

dropdownList.dataProvider = dp;
dropdownList.dropdown.setStyle( "cellRenderer", AlternatingRowColors ); // この行が背景設定のクラス定義。

 うーむ、なんつーか回りくどい。
 しかも、AlternatingRowColors.asで使われてる_listDataってもの凄い裏技臭のする変数なんですけど。
 この_listDataの中味はfl.controls.listClasses.ListDataだから、ListDataが持っているプロパティやメソッドが使える。AlternatingRowColors.asではindexが使われている。
 

ComboBoxの内容で文字色を変える

 えーと次はデータの内容によってセルの表示状態を変えるのね。
 同じ記事の「Setting background color based on a row's data」が参考になりそう。

 あーCustomRowColors.asを見ると、CellRendererクラスを継承(◁─)して、drawBackground()をoverrideしたところからは_listDataの他に、dataって値にいきなりアクセスできる。
  dataにはdataProviderからCellRendererに割当てられた項目が入っている。項目はdataProviderに設定した値によってObjectだったりXMLだったりする。
 ここで labelを取ればいい…けど_listDataのlabelでもいいな。
 そんでもって、setStyle()で"textFormat"を指定してやれば、文字の色指定ができそうだ。

//!-- UTF8
package {
import fl.controls.listClasses.CellRenderer;
import fl.controls.listClasses.ICellRenderer;
import flash.text.TextFormat;

public class TintTextColors extends CellRenderer implements ICellRenderer {
	private var prefectureTf:TextFormat = new TextFormat();
	private var otherTf:TextFormat = new TextFormat();
	
	public function TintTextColors():void {
		prefectureTf.color = 0x000000;
		otherTf.color = 0xff0000;
		super();
	}
	
	public static function getStyleDefinition():Object {
		return CellRenderer.getStyleDefinition();
	}
	
	override protected function drawBackground():void {
		if ( 0 < data.label.indexOf( "県" ) ) {
			setStyle( "textFormat", prefectureTf );
		} else {
			setStyle( "textFormat", otherTf );
		}
		super.drawBackground();
	}
}
}

 とまぁこんな感じで。"TintTextColors.as"で保存して、dropdownList.dropdown.setStyle( "cellRenderer", TintTextColors );でレンダラを指定するのを忘れずに。
 これで県がつかないとこだけ赤くなる。都道府県を選ぶ時に、多少色がついてた方が選びやすいと思うね。
 これから都道府県選択インタフェースを作る場合に、北海道・東北・関東・中部・近畿・中国・四国・九州の地域毎に交互に色分けしてみてはどうでしょーか。
 なお、textFormatは片方設定したらデフォルトの方は設定しないでおいたらいいんじゃないかと思ったんだけど、スクロールした場合に設定が残り続けるので、全パターン必ず設定する必要があります。ごチューイ。

 あ…drawBackground()じゃなくて、drawLayout()メソッドの方を使えば、textFieldってプロパティが使えて、setStyleを使わなくてもいいのか…まぁどっちでもいいか…良くないけど。
 しかしこのへんの内容ってリファレンスのどこに書いてあるんだか分かんないなー。

fl.controls.ComboBox

 次はコンボボックスだけど、これはeditableプロパティをtrueにしとけばいい。
 しかしこのデザインはコンボボックス(文字入力可能)だと分かりにくい、というか分からん。ドロップダウンリストと一緒の見た目で文字入力のところ凹んでないんだもんなー。
 前に書いたけど、Flash開発チームにはまともなユーザインタフェースデザイナがいないなぁ。

 コンボボックスの場合はユーザの文字入力が発生するので、ドロップダウンリストとはかなり扱いが異なる。
 具体的にはまずイベント、changeイベントが文字の入力の度に発生すること、ドロップダウンリストの時にはなかったenterイベントが発生する事。
 そして選択した項目の取り方。…が違うはずだが実際どう違うんだ?

dropdownList.addEventListener( Event.CHANGE, changeHandler );

function changeHandler( e:Event )
{
	trace( e.target.selectedItem );
}

 うおっ、文字入力した際のe.target.selectedItemの値がnullだっ。
 選択した場合もテキストフィールドが書き変わるので、e.target.textField.textを読むといいようだ。と思ったけど、選択した場合はひとつ前のが取れちゃうな、うーむ。
 本当にドロップダウンリストとテキストフィールドを組み合わせただけ、という雰囲気。

 で、成果。鳶嶋工房 / User Interface / Terms / コンボボックス(combo box)
 これはちょっと例としてはよろしくないので、そのうち変えるかも。

ひとつだけしか終わりませんでした

 

 今日はここまで。


2011-02-16