Upload
johnda
View
69
Download
0
Embed Size (px)
DESCRIPTION
Flex カス タムコン ポーネン ト の 作 り 方. ( 有 )CO-CONV 最田 健一. 自己紹介. にとよん という名前でブログやってます. http://tech.nitoyon.com/. Agenda. Flex 概要 非カスタムコンポーネントな開発 カスタムコンポーネント開発 まとめ. 1. Flex 概要. Flash と ActionScript がベース. しかし. タイムラインが. ない. プログラマ用. Flash やってた人より. Java や C# 経験者 の方がとっつきやすい. 特徴. 豊富 な GUI パーツ. - PowerPoint PPT Presentation
Citation preview
Flex カスタムコンポーネントの作り方 ( 有 )CO-CONV
最田 健一
自己紹介
にとよん という名前でブログやってます
http://tech.nitoyon.com/
Agenda
1. Flex 概要2.非カスタムコンポーネントな
開発3.カスタムコンポーネント開発4.まとめ
1
Flex概要
Flash と ActionScript がベース
しかし
タイムラインが
ない
プログラマ用
Flash やってた人
より
Java や C#経験者の方がとっつきやす
い
特徴
豊富なGUI パー
ツ
XMLで配置
具体例<mx:Panel title=" パネル "> <mx:HBox> <mx:Button label=" ボタン "/> <mx:CheckBox label=" チェックボックス "/> <mx:RadioButton label=" ラジオボタン "/> <mx:ComboBox dataProvider="{array}"/> </mx:HBox></mx:Panel>
具体例<mx:Panel title=" パネル "> <mx:HBox> <mx:Button label=" ボタン "/> <mx:CheckBox label=" チェックボックス "/> <mx:RadioButton label=" ラジオボタン "/> <mx:ComboBox dataProvider="{array}"/> </mx:HBox></mx:Panel>
具体例<mx:Panel title=" パネル "> <mx:HBox> <mx:Button label=" ボタン "/> <mx:CheckBox label=" チェックボックス "/> <mx:RadioButton label=" ラジオボタン "/> <mx:ComboBox dataProvider="{array}"/> </mx:HBox></mx:Panel>
具体例<mx:Panel title=" パネル "> <mx:HBox> <mx:Button label=" ボタン "/> <mx:CheckBox label=" チェックボックス "/> <mx:RadioButton label=" ラジオボタン "/> <mx:ComboBox dataProvider="{array}"/> </mx:HBox></mx:Panel>
具体例<mx:Panel title=" パネル "> <mx:HBox> <mx:Button label=" ボタン "/> <mx:CheckBox label=" チェックボックス "/> <mx:RadioButton label=" ラジオボタン "/> <mx:ComboBox dataProvider="{array}"/> </mx:HBox></mx:Panel>
流行し始め
Anywhere.FM http://www.anywhere.fm/player/
SearchMash ( Google の検索実験サイト)
Google Analytics AIR beta
※ これは AIR だが UI は Flex で作られている
弊社某案件
2
非カスタムコンポーネント
な開発
鉄則
可能な限り既存のコンポ
ーネントを使おう
複雑な塊には複合コンポーネントを定義
例
<?xml version="1.0" encoding="utf-8"?><mx:Application xmlns:mx="http://www.adobe..."> <mx:Label text=" 春休み "/> <mx:HBox> <mx:DateField/> <mx:Label text=" ~ "/> <mx:DateField/> </mx:HBox></mx:Application>
<?xml version="1.0" encoding="utf-8"?><mx:Application xmlns:mx="http://www.adobe..."> <mx:Label text=" 春休み "/> <mx:HBox> <mx:DateField/> <mx:Label text=" ~ "/> <mx:DateField/> </mx:HBox></mx:Application>
<?xml version="1.0" encoding="utf-8"?><mx:Application xmlns:mx="http://www.adobe..."> <mx:Label text=" 春休み "/> <mx:HBox> <mx:DateField/> <mx:Label text=" ~ "/> <mx:DateField/> </mx:HBox></mx:Application>複合コンポーネント化
<?xml version="1.0" encoding="utf-8"?><mx:Application xmlns:mx="http://www.adobe..." xmlns:comp="*">
<mx:Label text=" 春休み "/>
<comp:DateRange/>
</mx:Application>
<?xml version="1.0" encoding="utf-8"?><mx:HBox xmlns:mx="http://www.adobe .com/2006/mxml"> <mx:DateField> <mx:Label text=" ~ "/> <mx:DateField/></mx:HBox>
DateRange.mxml
利点
構造がすっきり
実装の責任範囲が明確に
再利用性UP
注意点
大きなクラスも問題だが
分けすぎにも注意
バランスが大事
既存のコンポーネントに不
満があれば
3
カスタムコンポーネント開
発
大きく分けて
3通りの方法
1 既存コンポーネントの拡張
2 既存コンポーネントの再実装
3 新規コンポーネント
1 既存コンポーネントの拡張既存コンポーネン
トを継承して
機能を追加
コンポーネントのクラス階
層
UIComponent
Button
ScrollControlBase
ListBase
Tree DataGrid
UIComponent
ListBaseButton
Tree DataGrid
ScrollControlBase
MyTree
MyButton
新たなプロパティやメソッドを
追加できる
protected なメソッドやプロパティを使って色々できる
super の前後に
コードを入れて色々できる
もしも、継承では限界がある場合は
つまり、
private にアクセス
したいときは
2 既存コンポーネントの再実装
既存コンポーネントのソースをコピーして
一部書き換える
UIComponent
ListBaseButton
Tree DataGrid
ScrollControlBase
MyTree
MyButton
コピー
コピー
mx.controls.Button
のソースコードは
frameworks\source\mx\controls\Button.as
mx.controls.Button
のソースコードは
frameworks\source\mx\controls\Button.as
(2,355 行 !!!)
あまりお薦めしない
ソースが煩雑になる
ライセンス的に微妙
開発は OKソース公開
NG詳しくは、、、 Flex SDKの「 license.htm 」をご覧ください
23 新規コンポーネン
ト
1からコンポーネントを
作る場合
UIComponent
Button
ScrollControlBase
ListBase
Tree DataGrid
MyComp
UIComponent を継承する
UIComponent って何?
その前に、ありがちな
実装例
円を描画するコンポーネン
ト
<mx:Application xmlns:mx="http://www..."
xmlns:comp="*"> <comp:Circle text="test" color="#ffffff" backgroundColor="#336699" width="100" height="100"/></mx:Panel>
使用例
Package {import flash.text.*;import flash.events.Event;import mx.core.UIComponent;
public class Circle extends UIComponent {// テキストprivate var textField:TextField;
(つづく) }}
実装例 (1/6) – クラス定義
/****** color プロパティ ******/ // 変数定義 private var _color:uint;
// getter public function get color():uint { return _color; }
// setter public function set color(value:uint):void { _color = value; dispatchEvent(new Event("colorChange")); }
実装例 (2/6) – プロパティ
/****** backgroundColor プロパティ ******/ // 変数定義 private var _backgroundColor:uint;
// getter ・ setter は同様のため略
/****** text プロパティ ******/ // 変数定義 private var _text:String;
// getter ・ setter は同様のため略
実装例 (3/6) – プロパティ(cont.)
// コンストラクタ public function Circle() { // TextField 作成 textField = new TextField(); addChild(textField);
// イベント登録 addEventListener("colorChange", colorChangeHandler); addEventListener("backgroundColorChange",
bgColorChangeHandler); addEventListener("textChange", textChangeHandler); }
実装例 (4/6) – コンストラクタ
private function colorChangeHandler(event:Event):void { render(); }
private function bgColorChangeHandler(event:Event):void { render(); }
private function textChangeHandler(event:Event):void { render(); }
実装例 (5/6) – イベントハンドラ
// 描画処理 private function render():void { graphics.clear(); graphics.beginFill(backgroundColor); graphics.drawEllipse(0, 0, unscaledWidth, unscaledHeight); graphics.endFill();
var tf:TextFormat = textField.getTextFormat(); tf.color = color; tf.size = 30; textField.defaultTextFormat = tf; textField.text = text ? text : ""; }
実装例 (6/6) – 描画処理
できた!
問題点
イベント処理が煩雑
プロパティの数だけ
イベントハンドラが増える
パフォーマンスの問題
circle.text = "hoge";circle.color = 0xffff00;circle.backgroundColor = 0xff0000;
このコードは描画処理が3回走る
UIComponentで解決!
無効化メソッドの活用
// setter public function set color(value:uint):void { _color = value; dispatchEvent(new Event("colorChange")); invalidateDisplayList(); }
setter で無効化メソッドを呼
ぶ
次の画面更新で描画処理が
行われる
invalidateDisplayList()
addEventListenerとイベントハンドラは、いらないの
で削除
override protected function updateDisplayList(w:Number, h:Number):void {
super.updateDisplayList(w, h); // 忘れずに !! render();}
updateDisplayListで描画する
1度でも無効化されると、次の画面更新
でFlex システムが
呼び出すメソッド
updateDisplayList()
circle.text = "hoge";circle.color = 0xffff00;circle.backgroundColor = 0xff0000;
3回 invalidate されるが
描画処理は1回だけ
(補足)無効化メソッ
ド3種類
1. 描画処理invalidateDisplayList
↓updateDisplayList
2. サイズ処理
invalidateSize↓
measure
3. プロパティ変更処理
invalidateProperties
↓commitProperties
さらにチューニング
// change フラグ private var colorChanged:Boolean = false;
// setter public function set color(value:uint):void { _color = value; colorChanged = true;
dispatchEvent(new Event("colorChange")); invalidateDisplayList(); }
changed フラグを導入
// 描画処理 private function render():void { // ( 略 )
if(colorChanged) { colorChanged = false;
var tf:TextFormat = textField.getTextFormat(); tf.color = color; tf.size = 30; textField.defaultTextFormat = tf; }
textField.text = text ? text : ""; }
changed フラグが true のときのみ描画に反映
// 描画処理 private function render():void { // ( 略 )
if(colorChanged) { colorChanged = false;
var tf:TextFormat = textField.getTextFormat(); tf.color = color; tf.size = 30; textField.defaultTextFormat = tf; }
textField.text = text ? text : ""; }
changed フラグが true のときのみ描画に反映
この部分が重い処理の場合に速度が向上する
さらにさらに
チューニング
// コンストラクタpublic function Circle() { // TextField 作成 textField = new TextField(); addChild(textField);}
コンストラクタで子を作成するのをやめる
// コンストラクタpublic function Circle() {}
override protected function createChildren(){ super.createChildren();
// TextField 作成 textField = new TextField(); addChild(textField);}
コンストラクタで子を作成するのをやめる
createChildren() は addChild されたとき
にFlex が呼ぶメソッド
new だけされてaddChild されない場合、
パフォーマンスが向上するだけでなく
初期化のコードをcreateChildren() に
集約できる
無効化メソッド・ createChildr
enの嬉しいところ
コーディングは
煩雑になるが多少
書く場所が一意に定まる
スパゲッティになりがちなUI をすっきり
書ける
UIComponentこそが
Flex の肝
UIComponentは
フレームワークだ
4
まとめ
• 基本は標準コンポーネントを使う
• 不満があれば継承して拡張する• どこにもなければ、 UICompon
ent を継承して、1から作る
参考資料
• Flex コンポーネントの作成と拡張flex2_createextendcomponents.pdf
• 前回よりは成長したブログhttp://d.hatena.ne.jp/s-ohira/