TWaver最大的優點之一是“
靈活的定制功能”。光說不練不行,來個例子演練一下:定制Tree節點的標簽。
- 默認Tree和Network上的標簽顯示的是網元的name屬性,設置Styles.TREE_LABEL屬性后,可以讓Tree顯示Styles.TREE_LABEL的值,以達到Tree和Network顯示不同標簽的目的
- 如果覺得這樣還不夠,可以設置Tree#labelFunction,比如下面的代碼可以讓Node顯示name,Link顯示Styles.TREE_LABEL:
1 tree.labelFunction = function(e:IElement):String{
2 if(e is Link){
3 return e.getStyle(Styles.TREE_LABEL);
4 }else{
5 return e.name;
6 }
7 }
既然TWaver這么靈活,那Tree的展開合并圖標能定制么?
先來看看用最原始的方式:
- 先定義2個class:
1 [Embed(source="assets/plus.png")]
2 [Bindable]
3 public var plus:Class;
4
5 [Embed(source="assets/minus.png")]
6 [Bindable]
7 public var minus:Class;
- 再設置Tree的disclosureOpenIcon和disclosureClosedIcon屬性為上面定義的class
1 <tw:Tree id="tree2" width="100%" height="100%" disclosureOpenIcon="{minus}"
2 disclosureClosedIcon="{plus}"/>
效果如下:
有同學就要問了,這樣還是不夠靈活,資源文件直接嵌入了SWF中,如果想換個圖標,還得重新編譯打包上傳一把。這好說,可以用css定制組件樣式(
其實css也要編譯成swf,這點adobe完全沒有考慮到用戶的實際需求,換個顏色還得編譯swf,以后有時間給大家說說如何不編譯swf也能用css定制樣式),但是偏偏disclosureOpenIcon和disclosureClosedIcon無法用css定制樣式。從mx.controls.Tree的源代碼中可以看到
1 [Style(name="disclosureOpenIcon", type="Class", format="EmbeddedFile", inherit="no")]
2 [Style(name="disclosureClosedIcon", type="Class", format="EmbeddedFile", inherit="no")]
3
這說明,disclosureOpenIcon和disclosureClosedIcon的style類型為class,css可以加載class?肯定不行,不信邪的同學可以試試:
1 <mx:Style>
2 Tree {
3 disclosureOpenIcon: "assets/minus.png";
4 disclosureClosedIcon: "assets/plus.png";
5 }
6 </mx:Style>
運行程序會得到下面的錯誤:
TypeError: Error #1034: Type Coercion failed: cannot convert “assets/plus.png” to Class.
at mx.controls::Tree/initListData()[C:\autobuild\3.5.0\frameworks\projects\framework\src\mx\controls\Tree.as:2663]
那我們就定義兩個class,但是這兩個class是什么class?我們來分析一下:
- 既然是圖片,我們就繼承Image組件吧。
- 既然是class,說明mx內部會不停地new這個class,所以圖片資源要緩存起來。
- 加載圖片是異步的,所以要等圖片加載完成后,再注冊這個class。
因此就有了這2個類的定義:
1 package {
2 import flash.display.Bitmap;
3 import flash.display.Loader;
4
5 import mx.controls.Image;
6
7 public class disclosureOpenIcon extends Image {
8 public static const loader:Loader = new Loader();
9
10 public function disclosureOpenIcon() {
11 this.source = new Bitmap(Bitmap(loader.content).bitmapData);
12 this.width = loader.content.width;
13 this.height = loader.content.height;
14 }
15 }
16 }
17
18 package {
19 import flash.display.Bitmap;
20 import flash.display.Loader;
21
22 import mx.controls.Image;
23
24 public class disclosureClosedIcon extends Image {
25 public static const loader:Loader = new Loader();
26
27 public function disclosureClosedIcon() {
28 this.source = new Bitmap(Bitmap(loader.content).bitmapData);
29 this.width = loader.content.width;
30 this.height = loader.content.height;
31 }
32 }
33 }
下面是定制Tree展開合并圖標的代碼:
1 private static function registTreeDisclosureIcon(tree:UIComponent):void {
2 registClassStyle(tree, disclosureOpenIcon, "assets/minus.png");
3 registClassStyle(tree, disclosureClosedIcon, "assets/plus.png");
4 }
5
6 private static function registClassStyle(component:UIComponent, clazz:Class, value:String):void {
7 if(clazz["loader"].content == null){
8 clazz["loader"].contentLoaderInfo.addEventListener(Event.COMPLETE, function(e:Event):void {
9 component.setStyle(getQualifiedClassName(clazz), clazz);
10 });
11 clazz["loader"].load(new URLRequest(value), new LoaderContext(true));
12 }
13 }
如果想全局注冊,可以考慮下面的代碼:
1 private static function registTreeDisclosureIcon():void {
2 var css:CSSStyleDeclaration = StyleManager.getStyleDeclaration("Tree");
3 registClassStyle(css, disclosureOpenIcon, "assets/minus.png");
4 registClassStyle(css, disclosureClosedIcon, "assets/plus.png");
5 }
6
7 private static function registClassStyle(css:CSSStyleDeclaration, clazz:Class, value:String):void {
8 if(clazz["loader"].content == null){
9 clazz["loader"].contentLoaderInfo.addEventListener(Event.COMPLETE, function(e:Event):void {
10 css.setStyle(getQualifiedClassName(clazz), clazz);
11 });
12 clazz["loader"].load(new URLRequest(value), new LoaderContext(true));
13 }
14 }
最后看看擺脫mx.controls.Tree的
FastTree怎么定制展開合并圖標,比如下面的代碼就讓展開合并圖標顛倒了:
1 tree4.expandIcon = "collapsed_icon";
2 tree4.collapseIcon = "expanded_icon";
本文完整代碼見附件:
TreeDisclosureIcon