Jun 26

本教程所需工具:FlexBuilder 3, Flash CS3;OS:Windows XP

先来看一下整套KingnareStyle的整体效果:

KingnareStyle-Skin

Search-256x256 Demo | Download Full Project | Download project from Downloadhere.

FLEX3.0组件可以通过CSS来控制样式,这里的CSS和平时编写网页时所谈及的CSS是有区别的,可以说是为FLEX量身定制的样式表,借助ActionScript可以实现强大的显示效果,下面的示例中会有相关介绍。

Adobe公司发布的Express Photoshop,黑色风格很令人着迷,KingnareStyle就是以它为原型制作的一款FLEX皮肤。皮肤包含的组件很多,限于篇幅,只能选取有代表性的组件做演示。下面以Button组件为例,开始FLEX皮肤制作的入门。


我们先在Flex Builder 3中新建一个项目FlexSkinTest

clip_image002

新建文件夹style,并在style文件夹下新建style.css文件:

clip_image004

双击打开style.css,切换到Design面板并新建一个样式:

clip_image006

选择Button组件:

clip_image008

按下OK后可以看到按钮的8种状态。便于测试,我们把背景色调整为0×333333:

clip_image010

切换到Source面板调整字体样式:

  1. Button
  2. {
  3. color:#AAAAAA;/*Color*/
  4. textRollOverColor:#FFFFFF; /*text rolling over color*/
  5. textSelectedColor:#FFFFFF; /*SelectedColor*/
  6. disabledColor:#5A5A5A; /* disabledColor */
  7. fontWeight:normal; /*fontweight*/
  8. }

结果如下图:

clip_image012

接下来的工作就是把按钮的8种状态用自定义的皮肤替换掉。

常用的实现方法有4种,我们将逐步介绍。

我们先学习KingnareStyle中Button组件皮肤的实现方法:将外部swf文件里的皮肤元件嵌入到组件样式文件中。

嵌入swf文件中的元件

首先在style文件夹下新建文件skin.fla,背景色同样设置为#333333。

CTRL+F8新建影片剪辑Button_upSkin,属性设置如下:

clip_image014

这里最好启用9切片,以后嵌入FLEX样式时就不用进行9切片设置了。

关于9切片,可以参考下面图示(引自Flex Developer Center):

clip_image015

将舞台放大至400%,使用矩形工具画一个空心矩形,坐标为(0,0),厚度为1像素,高宽均为23像素,填充色为#FFFFFF,透明度10%

clip_image017

再新建一个层,用同样的方法在内部画一个空心矩形,坐标为(1,1),厚度1像素,高宽均为21像素,填充色为#000000,透明度60%

clip_image019

下面填充空白区。

新建一个层,画实心矩形,坐标为(2,2),高宽均为19像素,填充线性渐变色白色,透明度由10%至0%:

clip_image021

最后再加高亮框。新建一个层,画空心矩形,坐标为(2,2),厚度为1,高宽均为19像素,填充线性渐变色白色,透明度由8%至3%

clip_image023

至此,图形部分完成,再把9切片的线重新定位:

clip_image025

CTRL+ENTER发布程序。

Flash部分告一段落,回到FLEX的style.css中。切换到Source面板,在Button样式中加入下面语句:

  1. upSkin:Embed(source=”skin.swf”, symbol=”Button_upSkin”);

解释一下,upSkin,Button弹起状态皮肤。Embed语句,用于将外部资源嵌入程序中使用,本例中将skin.swf中的Button_upSkin元件嵌入到样式中。

保存后切换到Design面板,会发现up状态已经更新为我们刚才制作的元件了:

clip_image027

使用同样的方法来制作其他状态皮肤,要注意给元件赋合适的名字。最后CCS如下:

  1. Application
  2. {
  3. backgroundGradientAlphas: 1.0, 1.0;
  4. backgroundGradientColors: #333333, #333333;
  5. }
  6.  
  7. Button
  8. {
  9. color: #AAAAAA;
  10. textRollOverColor: #FFFFFF;
  11. textSelectedColor:#FFFFFF;
  12. disabledColor:#5A5A5A;
  13. fontWeight:normal;
  14. upSkin: Embed(source=”skin.swf”, symbol=”Button_upSkin”);
  15. overSkin: Embed(source=”skin.swf”, symbol=”Button_overSkin”);
  16. downSkin: Embed(source=”skin.swf”, symbol=”Button_downSkin”);
  17. disabledSkin: Embed(source=”skin.swf”, symbol=”Button_disabledSkin”);
  18. selectedUpSkin: Embed(source=’skin.swf’, symbol=’Button_selectedUpSkin’);
  19. selectedOverSkin: Embed(source=’skin.swf’, symbol=’Button_selectedOverSkin’);
  20. selectedDownSkin: Embed(source=’skin.swf’, symbol=’Button_selectedDownSkin’);
  21. selectedDisabledSkin: Embed(source=’skin.swf’, symbol=’Button_selectedDisabledSkin’);
  22. }

效果图:

clip_image029

接下来我们打开FlexSkinTest.mxml文件,切换到Source面板,

添加 <mx:Style source="style/style.css"/>

<mx:Button x="10" y="10" label="Button"/>

换到Design面板,可以看到新加的Button组件已经应用我们的样式了,也可以多拖几个Button到程序中并设置不同的大小,可以发现边缘并未因形变发生模糊,这是我们使用了9切片的结果。

clip_image031

可以说,我们的Button组件皮肤已经完工了。

使用Flex Skin Design Extensions for Flash CS3

我们再开始第二种皮肤制作方法。

先做准备活动:

http://www.adobe.com/go/flex3_cs3_swfkit下载Flex Component Kit for Flash CS3。

http://www.adobe.com/go/flex3_skinning下载Flex Skin Design Extensions for Flash CS3.安装后重启Flash CS3.

http://livedocs.adobe.com/flex/3/skinning_extensions_flex3.pdf下载操作手册。

从上面地址中还可以看到有For Fireworks,For Photoshop等FLEX皮肤制作插件,我们可能在后续文章中介绍实现方法。

首先打开Flash CS3,CTRL+N新建文件,切换“新建文档”到“模板”面板,选择Flex Skins->Button,如下图:

clip_image033

将文件命名为skintemplate.fla,背景色调整#333333。

新建成功后,可以看到舞台上的按钮元件。双击按钮元件进入编辑状态,或者在库中双击Button_skin元件。可看到如下图所示的时间轴:

clip_image035

简略的介绍一下这些层的用途。

States:定义对应组件的每种状态时间线上的关键帧,如上图所示中的关键帧帧名

Transitions:定义组件状态切换时的过渡动画,默认为每种状态的最后两个关键帧为起始帧和终止帧,以up状态切换到over状态举例,Transitions层的up-over:start帧为起始帧,up-over:end帧为终止帧,可在art层中制作相应的过渡动画

Art:组件的图形部分

你会发现程序只生成了4种状态,通过前面的学习知道Button组件可以有8种状态,没关系,我们在disabled后面再加入4个状态(注意区分大小写):

clip_image037

以selectedUp状态为例:

States层关键帧名为selectedUp.

Transitions层,在最后两帧增加down-selectedOver:start, down-selectedOver:start两个关键帧作为过渡动画的起始与终止帧.

将前面制作的skin.fla中的Button组件皮肤移植过来。

例如up状态的:

clip_image039

所有状态完成后,CTRL+ENTER发布程序,这时会生成skintemplate.swf和skintemplate.swc两个文件。

然后我们切换到FLEX Builder 3,打开style.css,为了测试新的皮肤,我们要将之前的8种皮肤嵌入语句全部注释掉。切换到Design面板,注意右边属性面板中的Skin属性:

clip_image041

选择”Flash symbols…”

clip_image043

加入刚才生成的 skintemplate.swc的路径,选择Button_skin元件,点击OK

clip_image045

左侧预览区已经自动刷新成最新制作的皮肤了:

clip_image047

其实前两种方法原理类似,只是实现过程有些区别。

嵌入Image文件

除了选取SWF文件的元件嵌入皮肤资源外,还可以选择Image作为嵌入资源。

首先制作所需Image,以Button组件的Up状态为例,这里使用Fireworks CS3制作了buttonUp.png,制作过程与方法1相似,这里不再复述,得到图片如下图所示:

clip_image049

接下来进入Flex Builder 3,打开style.css,删除前两例中的皮肤嵌入代码。

然后在右侧面板中选择”Image files…”

clip_image051

在弹出的对话框中将Up状态的Image地址填入我们刚才制作的buttonUp.png。

clip_image053

OK之后左侧preview区可以看到Up状态已经更新了,但是还有重要的一步未做。

我们再点击右上角的“Edit Scale Grid”,编辑9切片数值。

clip_image055

调整四条虚线到合适位置:

clip_image057

完成后再次点击“Edit Scale Grid”

切换到Source面板,可以看到自动生成的代码:

  1. upSkin: Embed(source=”buttonUp.png”,scaleGridLeft=”3″,scaleGridTop=”3″,scaleGridRight=”61″,scaleGridBottom=”20″);

熟练后,可以直接写代码而不用手动设置了。

由于时间和篇幅限制,这里只完成Up状态皮肤了,其他状态的皮肤可由您来完成。

ActionScript皮肤编程

通过前面三种方法,估计你已经对整个皮肤制作过程有了大概的了解,如果要制作较高级皮肤就得借助ActionScript来实现了。

先来看看CSS中的例句:

  1. upSkin:ClassReference(“UpSkinClass”);

其中UpSkinClass就是我们要实现的皮肤类。

打开Flex Builder 3,在src文件夹下新建skins文件夹,并在skins文件夹下新建类文件:ButtonSkin.as,如下图所示:

clip_image059

我们选择mx.skins.Border作为superclass。

为什么要选择Border类呢?我们先来了解一下几个可以用于皮肤编程的superclass。

ProgrammaticSkin:实现了IFlexDisplayObject,ILayoutManagerClient,IInvalidating,ISimpleStyleClient接口,是最为容易和通用的superclass。

Border: ProgrammaticSkin的子类,并且加入了borderMetrics属性,如果皮肤有border属性可以使用这个类。

RectangularBorder:Border的子类,支持backgroundImage样式。

UIComponent:实现了IStateCleint接口,易于制作多状态的组件皮肤,也是实现MXML皮肤时所需的组件。

以上四个类的详细介绍可参考官方文档。

好了,我们再回到程序中,通过重写Border类的updateDisplayList方法来实现皮肤的重绘:

  1. override protected function updateDisplayList(w:Number, h:Number):void
  2. {
  3. //Draw your Graphics.
  4. }

填充以下代码:

  1. override protected function updateDisplayList(w:Number, h:Number):void
  2. {
  3. var g:Graphics = graphics;
  4. g.clear();
  5. //draw outside border
  6. g.lineStyle(1, 0xFFFFFF, 0.1);
  7. g.drawRect(0, 0, w, h);
  8. //draw
  9. g.lineStyle(1, 0×000000, 0.6);
  10.  
  11. var gradientBoxMatrix:Matrix = new Matrix();
  12.  
  13. gradientBoxMatrix.createGradientBox(w, h, Math.PI/2, 0, 0);
  14. g.beginGradientFill(GradientType.LINEAR,[0xFFFFFF, 0xFFFFFF],[0.1,0.0],null,gradientBoxMatrix);
  15. g.drawRect(1, 1, w-2, h-2);
  16. g.endFill();
  17. g.lineGradientStyle(GradientType.LINEAR,[0xFFFFFF, 0xFFFFFF],[0.08,0.03],null,gradientBoxMatrix);
  18. g.drawRect(2, 2, w-4, h-4);
  19. }

保存后打开style.css文件,切换到Source面板,在Button组件样式下加入代码:

upSkin: ClassReference("skins.ButtonSkin");

注意类包名要写全。

再切换到Design面板,单击刷新按钮

clip_image061

我们的程序已经起作用了:

clip_image063

那么其他状态呢,每个状态都要写一个类吗?No!

还有一个重要的属性没有使用:name

这个name就是状态实例名称,例如”upSkin”,”overSkin”等。

用switch语句来判断不同的实例名称并进行不同的绘制:

  1. override protected function updateDisplayList(w:Number, h:Number):void
  2. {
  3. var g:Graphics = graphics;
  4. g.clear();
  5.  
  6. var gradientBoxMatrix:Matrix = new Matrix();
  7.  
  8. switch(name)
  9. {
  10. caseupSkin”:
  11. {
  12. //draw external border
  13. g.lineStyle(1, 0xFFFFFF, 0.1);
  14. g.drawRect(0, 0, w, h);
  15. //draw inner border and fill in gradual color
  16. g.lineStyle(1, 0×000000, 0.6);
  17. gradientBoxMatrix.createGradientBox(w, h, Math.PI/2, 0, 0);
  18. g.beginGradientFill(GradientType.LINEAR,[0xFFFFFF, 0xFFFFFF],[0.1,0.0],null,gradientBoxMatrix);
  19. g.drawRect(1, 1, w-2, h-2);
  20. g.endFill();
  21. //draw inner high-light border
  22. g.lineGradientStyle(GradientType.LINEAR,[0xFFFFFF, 0xFFFFFF],[0.08,0.03],null,gradientBoxMatrix);
  23. g.drawRect(2, 2, w-4, h-4);
  24. break;
  25. }
  26. case “overSkin”:
  27. {
  28. g.lineStyle(1, 0xFFFFFF, 0.1);
  29. g.drawRect(0, 0, w, h);
  30. g.lineStyle(1, 0×000000, 0.6);
  31. gradientBoxMatrix.createGradientBox(w, h, Math.PI/2, 0, 0);
  32. g.beginGradientFill(GradientType.LINEAR,[0xFFFFFF, 0xFFFFFF],[0.15,0.05],null,gradientBoxMatrix);
  33. g.drawRect(1, 1, w-2, h-2);
  34. g.endFill();
  35. g.lineGradientStyle(GradientType.LINEAR,[0xFFFFFF, 0xFFFFFF],[0.08,0.03],null,gradientBoxMatrix);
  36. g.drawRect(2, 2, w-4, h-4);
  37. break;
  38. }
  39. casedownSkin”:
  40. {
  41. break;
  42. }
  43. casedisabledSkin”:
  44. {
  45. break;
  46. }
  47. caseselectedUpSkin”:
  48. {
  49. break;
  50. }
  51. caseselectedOverSkin”:
  52. {
  53. break;
  54. }
  55. caseselectedDownSkin”:
  56. {
  57. break;
  58. }
  59. caseselectedDisabledSkin”:
  60. {
  61. break;
  62. }
  63. }
  64. }

上示代码只绘制了upSkin和overSkin两个状态的皮肤,其他的皮肤您可以尝试着完成。

如果觉得在样式表中每个状态的皮肤类都要指明很麻烦,可以使用以下语句:

  1. skin: Embed(skinClass=’skins.ButtonSkin’);

或:

  1. skin: ClassReference(”skins.ButtonSkin”);

最后效果如下:

clip_image065

(注:其他样式因为没有实现,所以只显示了Label)

MXML皮肤编程:

此外,我们还可以使用MXML文件来制作皮肤。仍以Button组件制作为例。

打开Flex Builder 3,在FlexSkinTest项目中新建文件夹components,在components文件夹下新建文件夹skins,skins文件夹下新建ButtonSkin.mxml文件:

clip_image067

重写updateDisplayList方法,并填充上个例子中的绘图语句。

  1. //fill in the inner array: alpha
  2. private var _innerFrameAlphas:Array = [0.1,0.0];
  3. //inner high-light alpha
  4. private var _innerHighlightAlphas:Array = [0.08,0.03];
  5.  
  6. override protected function updateDisplayList(w:Number, h:Number):void
  7. {
  8. var g:Graphics = graphics;
  9. g.clear();
  10.  
  11. var gradientBoxMatrix:Matrix = new Matrix();
  12. g.lineStyle(1, 0xFFFFFF, 0.1);
  13. g.drawRect(0, 0, w, h);
  14.  
  15. // draw inner border and fill in gradual color
  16. g.lineStyle(1, 0×000000, 0.6);
  17. gradientBoxMatrix.createGradientBox(w, h, Math.PI/2, 0, 0);
  18. g.beginGradientFill(GradientType.LINEAR,[0xFFFFFF, 0xFFFFFF],_innerFrameAlphas,null,gradientBoxMatrix);
  19. g.drawRect(1, 1, w-2, h-2);
  20. g.endFill();
  21.  
  22. //draw inner high-light border
  23. g.lineGradientStyle(GradientType.LINEAR,[0xFFFFFF, 0xFFFFFF],_innerHighlightAlphas,null,gradientBoxMatrix);
  24. g.drawRect(2, 2, w-4, h-4);
  25.  
  26. }

再打开style.css,更改嵌入语句:

skin: ClassReference("components.skins.ButtonSkin");

此时可以发现皮肤已经更新了:

clip_image069

但是所有皮肤都是相同的,接下来我们设置不同的属性值区分不同的状态皮肤。

这时就用到了invalidateDisplayList方法,这个方法会呼叫updateDisplayList方法更新组件。

我们把前面的两个变量_innerFrameAlphas和innerHighlightAlphas封装:

  1. public function get innerFrameAlphas():Array
  2. {
  3. return _innerFrameAlphas;
  4. }
  5. public function get innerHighlightAlphas():Array
  6. {
  7. return _innerHighlightAlphas;
  8. }
  9. public function set innerFrameAlphas(alphas:Array):void
  10. {
  11. _innerFrameAlphas = alphas;
  12. invalidateDisplayList();
  13. }
  14.  
  15. public function set innerHighlightAlphas(alphas:Array):void
  16. {
  17. _innerHighlightAlphas = alphas;
  18. invalidateDisplayList();
  19. }

之后在over这个State中,设置innerFrameAlphas和innerHighlightAlphas属性,重绘组件。

<mx:State name="over">

<mx:SetProperty target="{this}" name="innerFrameAlphas" value="{[0.15,0.05]}"/>

<mx:SetProperty target="{this}" name="innerHighlightAlphas" value="{[0.08,0.03]}"/>

</mx:State>

现在我们再发布一下,你会发现over状态的皮肤已经更新了。其余状态的皮肤您可尝试着完成,这里就不复述了。

最后,如果要在运行时加载皮肤,应把皮肤单独编译为SWF文件。

在CSS文件上右键->Comile CSS to SWF即可。

也可通过命令行“mxmlc style.css”来编译。

clip_image071

OK,在FLEX皮肤制作过程中,这几种方法是比较常用的,灵活运用可以使你的程序增色不少。

Cheers!

本文作者:auzn   英文版本首发于: Ntt.cc   翻译整理:minidxer  英文版本地址:

Using FlexBuilder 3 and Flash CS3 to Build Your Skin in Flex–KingnareStyle skin produce introduction

中英文版本均基于Creative Commons License

written by Minidxer  |  tags: , , , , ,

Related Post

18 Responses to “auzn经典Flex教程–KingnareStyle皮肤制作简介”

  1. 一亿度 Says:

    这个界面酷呆了! 要是有这样的wordpress主题就好了!

  2. Minidxer Says:

    那您可以动手做一个,造福一群人~ :)

  3. 一亿度 Says:

    目前还不会做主题:( 看来自己会做主题很有必要!

  4. opera Says:

    其实,这些主题的素材在懒人里面都有的。到里面下载一些然后做个修改一定不错。wordpress不错,赞一个!过段时间也来启用他。

  5. Minidxer Says:

    opera , ”懒人“ 的地址是什么?素材库还是做WordPress Theme的?

  6. opera Says:

    又是一个忡忡的周末~ 最近发现时间过得真快,快得有点心慌~

    安家说 周末愉快啦 :)

  7. Minidxer Says:

    BTW:“安家” 就是 opera 吗? 貌似我跟不上时代的步伐了。。。

  8. opera Says:

    懒人的素材库 是提供优秀的简单代码 省去自己写的麻烦。

    不是专门做WordPress Theme。

    BUT 可以用来做WordPress Theme。

    地址:你到google 搜懒人网 第一个就是

  9. Minidxer Says:

    是这个吗? http://www.makewing.com

  10. opera Says:

    yes

  11. Minidxer Says:

    东西的确不少,先记下了,需要的时候就到那里去取~, tks, op

  12. opera Says:

    里面东西确认不少,呵呵 我也经常去那里找东西。

    所以说 网上的东西 不怕你找不到,只怕你想不到。 :)

  13. Minidxer Says:

    “网上自有黄金屋,网上自有严如玉”?呵呵

  14. opera Says:

    :(

    是颜如玉 是我本家啊 呵呵

  15. Minidxer Says:

    汗,我一直以为是这个“严“,原来是这个“颜“。。。我去google一下颜如玉有什么传说,呵呵

Trackbacks

Leave a Reply