Flex/AIRでアプリケーションを開発したことがある。
初級
ADB(Adobe Developer Box)では、おすすめ情報やRSSフィード、PDF検索結果をリスト表示します。連載の第3回目は、ADBでも使用したリストの作成について紹介したいと思います。
さて、リストの作成ですが、Flexに備わるコンポーネントをそのまま使うだけでは実現できそうにありませんのでカスタムコンポーネントを作成する事になります。
リスト作成のアプローチはいくつかあります。
筆者も経験しましたが、「Spriteをベースに一から実装する」には時間がかかりますが、制約が無いので思い通りのリストが作れます。
FlexのListやTileListなどを利用したリストの作成は、こちらに詳しく書かれていますのでここでは紹介しません。
今回は、最後の「VBoxを利用して実装する」というアプローチにトライします。
今回作成するサンプルの完成イメージは以下のようなものです。
このリストは、以下の構成要素に分解することができます。
ではこれらを順番に作成してゆきましょう。
サンプルのイメージは、書籍リストです。表示する要素は、サムネイル、書籍名、著者、発行日とします。
まずは単体のリスト要素データを表す Book クラスを作成します。
package sample.vo
{
public class Book
{
public var thumbnail:String;
public var title:String;
public var author:String;
public var publishDate:String;
}
}
次に、リスト要素データ配列を作成します。データは固定で10件とします。
package sample.vo
{
public class DataGenerator
{
public static var data:Array
= [["http://images.amazon.com/images/P/4798020435.01.THUMBZZZ.jpg",
"Flex3プログラミング入門",
"宮田 亮",
"2008/8"],
["http://images.amazon.com/images/P/484432649X.01.THUMBZZZ.jpg",
"Adobe Flex 3 & AIRではじめるアプリケーション開発",
"公門 和也、大谷 晋平、 堀越 悠久史",
"2008/12/1"],
・・・以下省略・・・
];
}
}
作成したデータをArrayCollection にして返却する関数を作成します。
// DataGeneratorクラス内
public static function generate():ArrayCollection
{
var array:ArrayCollection = new ArrayCollection();
for (var i:int=0; i < data.length; i++)
{
var book:Book = new Book();
book.thumbnail = data[i][0];
book.title = data[i][1];
book.author = data[i][2];
book.publishDate = data[i][3];
array.addItem(book);
}
return array;
}
これで、リスト要素データ配列が作成できました。
実際にはRemoteObjectなどを使用してサーバーサイドから取得することが多い部分かと思います。
次にリスト要素を作成します。サンプルでは Canvas を利用してレイアウトします。
リスト本体からは、data プロパティにBookデータが渡されるというルールにします。
package sample.listRenderers
{
public class Pack extends Canvas
{
public function get book():Book
{
return data as Book;
// リスト要素の作成中は以下のようにすると先に作成した
// データが使える。(ここでは先頭の1件)
return DataGenerator.generate().getItemAt(0) as Book;
}
}
}
このコンポーネントの作成中は、上記ソース中のコメントのように記述すると、先に作成したリスト要素配列データが利用できます。
さて、いよいよリスト本体を作成しますが、前述したように、今回は mx.containers.VBoxを利用する事にします。
VBox コンポーネントは、子オブジェクトを自動的に縦方向(垂直方向)に並べてくれるレイアウトコンテナです。VBoxは、子オブジェクトを縦に並べてゆき、子要素がVBox自身の高さを超えると自動的にスクロールバーを表示します。
試しに VBox にリスト要素を10件配置してみます
このソースは、以下のようなものです。
<mx:VBox width="620" height="400">
<listRenderers:Pack width="600" height="100" />
<listRenderers:Pack width="600" height="100" />
・・・途中省略・・・
<listRenderers:Pack width="600" height="100" />
</mx:VBox>
VBox が自動的に表示するスクロールバーをそのまま使うと、スクロールした時の動きがスムーズではありません。そこでTweenerというアニメーションライブラリを利用し、スムーズにスクロールするようにします。これについては、添付ソースのVBoxを継承したSmoothVBox クラスを参照して下さい。
VBox のままでは、リストとして成立しません。
大抵の場合、リスト要素となるデータは Array や ArrayCollection などの配列で保持しますので、リストコンポーネントに対して配列のデータを設定できるようにする必要があります。
リスト要素データは Flex の命名の例に従い、dataProvider とします。データが設定されたら自動的にリスト要素(Pack)を追加するようにします。
public class ListVBox extends SmoothVBox
{
// listRenderer(リスト要素(Pack))
private var _listRenderer:Class;
public function set listRenderer(value:Class):void
{
_listRenderer = value;
}
public function get listRenderer():Class
{
return _listRenderer;
}
// dataProvider(リスト要素データ)
private var _dataProvider:ArrayCollection;
public function set dataProvider(value:ArrayCollection):void
{
_dataProvider = value;
__addElements();
}
public function get dataProvider():ArrayCollection
{
return _dataProvider;
}
}
dataProvider がセットされたら __addElements()を呼び出し、リスト要素を生成します。リスト要素の生成は、一度に生成すると描画に時間がかかり、画面が固まったようになってしまう恐れがあります。そこで Event.ENTER_FRAME を利用して、1フレームにつき1つリスト要素を生成するようにします。
// ・・・ListVBox クラス内・・・
protected var __elementsArray:ArrayCollection = new ArrayCollection();
protected var __makeElementCounter:int = 0;
/**
* リスト要素の作成。負荷分散のため EnterFrame する。
*/
protected function __addElements():void
{
addEventListener(Event.ENTER_FRAME, __makeEnterFrameHandler);
}
/**
* リスト要素の生成用EnterFrameハンドラ関数
*/
protected function __makeEnterFrameHandler(event:Event):void
{
if (!__makeElement())
{
__resetMakeElement();
}
}
/**
* リスト要素の生成用EnterFrameハンドラ関数を中止する
*/
protected function __resetMakeElement():void
{
removeEventListener(Event.ENTER_FRAME, __makeEnterFrameHandler);
__makeElementCounter = 0;
}
/**
* リスト要素の生成
*/
protected function __makeElement():Boolean
{
if (!dataProvider) return false;
var element:Pack = new listRenderer();
element.percentWidth = 100;
element.data = dataProvider[__makeElementCounter];
addChild(element);
__elementsArray.addItem(element);
__makeElementCounter++;
return (__makeElementCounter < dataProvider.length);
}
スタイルシートを作成し、PackとScrollBar に対してスタイルを設定します。添付ソースの style.css を参照してください。ScrollBarのスタイル指定には、Skinを使用しています。スキンはADBGraphical.swf で、ADB用にFlashで作成したものです。(スキンの作成についての説明は今回は割愛させて頂きます。。。)
では最後に作成したコンポーネントを使ってみます。
<mx:Script>
<![CDATA[
import sample.listRenderers.Pack;
import sample.vo.DataGenerator;
]]>
</mx:Script>
<containers:ListVBox
dataProvider="{DataGenerator.generate()}"
listRenderer="{Pack}"
width="700" height="300"
/>
VBox を利用する方法でのリスト作成を紹介しました。今回のサンプルだけではまだまだ実用に耐えられるものではありません。
ADB(Adobe Developer Box)でも、リサイズ対応やハイライト、「↑」「↓」キーによる選択の変更、「表示中の必要なリスト要素しかaddChild()しない」など、いろいろなアイデアを盛り込みました。ADBは、ソースコードが公開されますので、リストの部分の実装について、一度覗いてみて頂ければ幸いです。
では、引き続き開発中のAdobe Developer Box !次回の連載をお楽しみに!!
ADB ( Adobe Developer Box ) は、Adobe AIR で作成された RIA開発者向けのデスクトップツールであり、Flex User Groupの大阪のメンバーが中心となって開発中のRIA開発者向けデスクトップツール。2009年1月末ごろ Adobe よりベータ版がリリースされる予定です。画像はウィジェットモードで起動中の ADBです。
Tutorials and samples |
AIR blogs |
More |
AIR Cookbooks |
More |
| 01/20/2012 | Skinnable Transform Tool |
|---|---|
| 01/18/2012 | Recording webcam video & audio in a flv file on local drive |
| 12/12/2011 | Date calculations using 'out-of-the-box' functions |
| 11/29/2011 | Button compatibility with NativeComboBox |