在上一篇文章中,為大家介紹了Flex中皮膚的簡單且基本也是最常用的用法,就是先在外部程序中做好皮膚樣式,之后再在Flex中加載這些皮膚資源,比如是PNG圖片,或者是SWF文件等,這些方法都是比較直接且方便簡單的。不過靈活性還是不太好,而現(xiàn)在這篇文章中要講的,就是從程序里AS編寫的皮膚,你可以更靈活自由地控制皮膚的樣式與表達(dá)方式等,而不用依賴于外部的圖片或SWF資源,不過這樣還是有些缺點(diǎn)的,就是擴(kuò)展或是改變時(shí)就比較不靈活,像圖片資源的皮膚的話,可以很輕易的改變不同的圖片的路徑資源等就可以修改了不同的皮膚模式,而用AS Graphics寫的皮膚的話,要修改一下那些代碼,當(dāng)然,你也可以在AS代碼里寫上動(dòng)態(tài)加載其它圖片資源又或者作一些更高級(jí)的效果等等。
先在這里解析一下,要以代碼方式自定義一個(gè)皮膚的話,需要自已編寫一個(gè)皮膚子類,繼承ProgrammaticSkin這個(gè)類,這個(gè)是所有編寫自定義皮膚的基類,該類也派生了另外兩個(gè)類:RectangularBorder 與 Border 類,都是差不多的,如果你是寫Icon之類的小皮膚的話,比如CheckBox或者RadioButton這類皮膚不需要太復(fù)雜的畫圖邏輯,而且大小固定,就像是一個(gè)小Icon吧,只是有幾個(gè)狀態(tài)而已,這類小皮膚的話,繼承ProgrammaticSkin就可以了,而寫一些復(fù)合的控件,背景大小可以調(diào)節(jié)之類的皮膚(其實(shí)就是大部分皮膚)就用Border或者RectangularBorder類。但都有一個(gè)相同點(diǎn),就是繼承了那些類之后,都必需覆蓋 updateDisplayList 這個(gè)方法,這個(gè)方法是由程序自動(dòng)調(diào)用,當(dāng)需要用到控件時(shí),需要控件的皮膚進(jìn)行表現(xiàn)時(shí),就會(huì)調(diào)用那個(gè)方法,所以你必需覆蓋它,并將你的畫圖邏輯代碼寫在那個(gè)方法里面。還有要注意的是,這個(gè)皮膚類會(huì)與你應(yīng)用這皮膚的控件的Style設(shè)置共享,也就是說你可以在編寫這個(gè)皮膚類代碼里面,使用getStyle()等等方法獲得設(shè)置在目標(biāo)控件中的風(fēng)格屬性,比如說是<mx:Panel backgroundColor="0xffffff" borderSkin="MySkin"> 那么你可以在MySkin代碼里獲取這個(gè)顏色值來進(jìn)行畫出該顏色的圖片或其它操作,而直接將顏色值寫死在代碼里是不規(guī)范的,就如我下面貼出來的的代碼,不過出于自已懶,快速代個(gè)示例代碼,所以犯這個(gè)錯(cuò)了。說多了,下面看看代碼先。
好了,我們先看看看代碼,這份代碼是寫了一個(gè)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 * 該方法當(dāng)在控件更新外觀時(shí)將會(huì)被自動(dòng)調(diào)用
16 * 會(huì)傳入兩個(gè)參數(shù)數(shù),第一個(gè)是Width,第二個(gè)是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這個(gè)屬性是父類里已經(jīng)提供了的
24 var p:Container = parent as Container; //獲取該皮膚所應(yīng)用在的父容器,這里為Panel
25
26 //這里需要注意,一定要判斷父容器是否已被設(shè)置,在文章里作解釋
27 if(p){
28 //獲取容器定義的區(qū)域邊界信息對(duì)象
29 var vm:EdgeMetrics = p.viewMetrics;
30 //設(shè)置四個(gè)角的圓度
31 var radiusContent:Object = {tl:vm.top,tr:0,bl:0,br:vm.top};
32 //標(biāo)題欄圓度
33 var radiusTitle:Object = {tl:vm.top,tr:0,bl:0,br:0};
34 //畫一個(gè)圓角矩形,整個(gè)背景
35 this.drawRoundRect(0,0,w,h,radiusContent,bg,ba);
36 //畫一個(gè)圓角矩形,標(biāo)題欄
37 this.drawRoundRect(0,0,w,vm.top,radiusTitle,0xff0000,.7);
38 //畫一個(gè)圓角矩形,標(biāo)題欄的那個(gè)高光水晶條
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 }
上面的代碼就是皮膚的代碼,之后你還要做的,就是將該皮膚應(yīng)用到Panel這個(gè)容器里:
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 這個(gè)屬性是Container控件所獨(dú)有的屬性,是一個(gè)只讀屬性,編寫Container子類的時(shí)候都要覆蓋它,是用于定義這個(gè)容器正文區(qū)與邊界值的,比如Canvas的四周都是0,所以沒有標(biāo)題欄與邊條,而Panel就有四周的邊界,而Top邊界比較大,用作顯示title的,所以如果你要做容器的皮膚的話,注意一下這個(gè)值。還有就是,為什么獲取了皮膚應(yīng)用的控件引用(parent)后還要判斷它是否為空?因?yàn)楫?dāng)程序加載到這個(gè)控件時(shí),是先加載那個(gè)皮膚的,所以parent的值未被設(shè)置,是空的,如果你不作判斷的話,將會(huì)出現(xiàn)空引用的錯(cuò)誤(parent.viewMetrics),當(dāng)加載完皮膚后,再加載控件并設(shè)置控件的屬性和設(shè)置皮膚,這時(shí)將會(huì)再次調(diào)用updateDisplayList的方法,這時(shí)parent才有值,就是那個(gè)控件的引用。當(dāng)改變了style或一些屬性后,又會(huì)自動(dòng)觸發(fā)調(diào)用updateDisplayList方法。
我們來看看最終運(yùn)行效果:
補(bǔ)充一下:
在第一篇文章里,說了將皮膚做在SWF文件里再加載,想一下,可以將該皮膚做成動(dòng)畫MC的,而不單單只是一個(gè)畫面,可以做成一些動(dòng)畫作為皮膚,之后在Flex引用該SWF的Symbol,這樣皮膚就有了動(dòng)畫效果了,不只只是單純的不動(dòng)的平面圖!
Flex中的皮膚教程就說到這里,皮膚還有很多可探索的,只要大家有求知欲,多點(diǎn)看看英文文檔,看看別人的例子程序代碼,現(xiàn)在Flex也開源了,也可以多看看Flex的源碼,會(huì)得到很多知識(shí)!
posted on 2008-07-29 14:40
姜大叔 閱讀(2436)
評(píng)論(2) 編輯 收藏 所屬分類:
Flash/Flex