在上一篇文章中,為大家介紹了Flex中皮膚的簡單且基本也是最常用的用法,就是先在外部程序中做好皮膚樣式,之后再在Flex中加載這些皮膚資源,比如是PNG圖片,或者是SWF文件等,這些方法都是比較直接且方便簡單的。不過靈活性還是不太好,而現(xiàn)在這篇文章中要講的,就是從程序里AS編寫的皮膚,你可以更靈活自由地控制皮膚的樣式與表達方式等,而不用依賴于外部的圖片或SWF資源,不過這樣還是有些缺點的,就是擴展或是改變時就比較不靈活,像圖片資源的皮膚的話,可以很輕易的改變不同的圖片的路徑資源等就可以修改了不同的皮膚模式,而用AS Graphics寫的皮膚的話,要修改一下那些代碼,當然,你也可以在AS代碼里寫上動態(tài)加載其它圖片資源又或者作一些更高級的效果等等。
先在這里解析一下,要以代碼方式自定義一個皮膚的話,需要自已編寫一個皮膚子類,繼承ProgrammaticSkin這個類,這個是所有編寫自定義皮膚的基類,該類也派生了另外兩個類:RectangularBorder 與 Border 類,都是差不多的,如果你是寫Icon之類的小皮膚的話,比如CheckBox或者RadioButton這類皮膚不需要太復雜的畫圖邏輯,而且大小固定,就像是一個小Icon吧,只是有幾個狀態(tài)而已,這類小皮膚的話,繼承ProgrammaticSkin就可以了,而寫一些復合的控件,背景大小可以調(diào)節(jié)之類的皮膚(其實就是大部分皮膚)就用Border或者RectangularBorder類。但都有一個相同點,就是繼承了那些類之后,都必需覆蓋 updateDisplayList 這個方法,這個方法是由程序自動調(diào)用,當需要用到控件時,需要控件的皮膚進行表現(xiàn)時,就會調(diào)用那個方法,所以你必需覆蓋它,并將你的畫圖邏輯代碼寫在那個方法里面。還有要注意的是,這個皮膚類會與你應用這皮膚的控件的Style設置共享,也就是說你可以在編寫這個皮膚類代碼里面,使用getStyle()等等方法獲得設置在目標控件中的風格屬性,比如說是<mx:Panel backgroundColor="0xffffff" borderSkin="MySkin"> 那么你可以在MySkin代碼里獲取這個顏色值來進行畫出該顏色的圖片或其它操作,而直接將顏色值寫死在代碼里是不規(guī)范的,就如我下面貼出來的的代碼,不過出于自已懶,快速代個示例代碼,所以犯這個錯了。說多了,下面看看代碼先。
好了,我們先看看看代碼,這份代碼是寫了一個Panel的皮膚:
1 package com.jiangzone
2 {
3 import mx.skins.Border
4 import mx.core.EdgeMetrics;
5 import mx.core.Container;
6 import mx.graphics.RectangularDropShadow;
7
8 public class MyPanelBorderSkin extends Border {
9
10 public function MyPanelBorderSkin():void {
11 }
12
13 /**
14 * 該方法必需要覆蓋,如果你要自定義自已的皮膚的話,
15 * 該方法當在控件更新外觀時將會被自動調(diào)用
16 * 會傳入兩個參數(shù)數(shù),第一個是Width,第二個是Height,即是該控件的寬與高
17 * */
18 override protected function updateDisplayList(w:Number,h:Number):void {
19 super.updateDisplayList(w,h);
20
21 var ba:uint = 1; //backgroundAlpha 背景透明度
22 var bg:uint = 0xffffff; //backgroundColor 背景顏色
23 graphics.clear(); //graphics這個屬性是父類里已經(jīng)提供了的
24 var p:Container = parent as Container; //獲取該皮膚所應用在的父容器,這里為Panel
25
26 //這里需要注意,一定要判斷父容器是否已被設置,在文章里作解釋
27 if(p){
28 //獲取容器定義的區(qū)域邊界信息對象
29 var vm:EdgeMetrics = p.viewMetrics;
30 //設置四個角的圓度
31 var radiusContent:Object = {tl:vm.top,tr:0,bl:0,br:vm.top};
32 //標題欄圓度
33 var radiusTitle:Object = {tl:vm.top,tr:0,bl:0,br:0};
34 //畫一個圓角矩形,整個背景
35 this.drawRoundRect(0,0,w,h,radiusContent,bg,ba);
36 //畫一個圓角矩形,標題欄
37 this.drawRoundRect(0,0,w,vm.top,radiusTitle,0xff0000,.7);
38 //畫一個圓角矩形,標題欄的那個高光水晶條
39 this.drawRoundRect(0,0,w,vm.top / 2,radiusTitle,0xffffff,.3);
40
41 //下面是畫陰影的。
42 var dropShadow:RectangularDropShadow = new RectangularDropShadow();
43 dropShadow.distance = 8;
44 dropShadow.angle = 60;
45 dropShadow.color = 0x000000;
46 dropShadow.alpha = 0.4;
47
48 dropShadow.tlRadius = radiusContent.tl;
49 dropShadow.trRadius = radiusContent.tr;
50 dropShadow.blRadius = radiusContent.bl;
51 dropShadow.brRadius = radiusContent.br;
52
53 dropShadow.drawShadow(graphics, 0, 0, w, h);
54 }
55 }
56 }
57 }
上面的代碼就是皮膚的代碼,之后你還要做的,就是將該皮膚應用到Panel這個容器里:
1 <mx:Application
2 xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="init()"
3 layout="absolute">
4
5 <mx:Style>
6 .myPanelSkin {
7 borderSkin: ClassReference( "com.jiangzone.MyPanelBorderSkin" );
8 }
9 </mx:Style>
10
11 <mx:Panel borderSkin="com.jiangzone.MyPanelBorderSkin"
12 width="200" height="150" x="24" y="23"/>
13
14 </mx:Application>
代碼很簡單,這里要說一下,viewMetrics 這個屬性是Container控件所獨有的屬性,是一個只讀屬性,編寫Container子類的時候都要覆蓋它,是用于定義這個容器正文區(qū)與邊界值的,比如Canvas的四周都是0,所以沒有標題欄與邊條,而Panel就有四周的邊界,而Top邊界比較大,用作顯示title的,所以如果你要做容器的皮膚的話,注意一下這個值。還有就是,為什么獲取了皮膚應用的控件引用(parent)后還要判斷它是否為空?因為當程序加載到這個控件時,是先加載那個皮膚的,所以parent的值未被設置,是空的,如果你不作判斷的話,將會出現(xiàn)空引用的錯誤(parent.viewMetrics),當加載完皮膚后,再加載控件并設置控件的屬性和設置皮膚,這時將會再次調(diào)用updateDisplayList的方法,這時parent才有值,就是那個控件的引用。當改變了style或一些屬性后,又會自動觸發(fā)調(diào)用updateDisplayList方法。
我們來看看最終運行效果:
補充一下:
在第一篇文章里,說了將皮膚做在SWF文件里再加載,想一下,可以將該皮膚做成動畫MC的,而不單單只是一個畫面,可以做成一些動畫作為皮膚,之后在Flex引用該SWF的Symbol,這樣皮膚就有了動畫效果了,不只只是單純的不動的平面圖!
Flex中的皮膚教程就說到這里,皮膚還有很多可探索的,只要大家有求知欲,多點看看英文文檔,看看別人的例子程序代碼,現(xiàn)在Flex也開源了,也可以多看看Flex的源碼,會得到很多知識!
posted on 2008-07-29 14:40
姜大叔 閱讀(2445)
評論(2) 編輯 收藏 所屬分類:
Flash/Flex