Skin是Flex 4.0的产品,旨在让开发者通过Skin表现组件的外观,进而实现皮肤外表与业务数据的分离。为组件定义一个Skin非常容易,如下示例即是一段简单的Skin代码。
<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx"> <!-- host component --> <fx:Metadata> [HostComponent("com.ajg.Components.BaseContainer")] </fx:Metadata> <!-- states --> <s:states> <s:State name="normal"/> <s:State name="open"/> <s:State name="closed"/> <s:State name="disabled"/> </s:states> </s:Skin>
Skin通过元数据的HostComponent以及样式的skinClass,与组件绑定,便实现了组件的皮肤功能。但是一个静态的皮肤固然是索然无味的,开发者经常需要通过与组件建立关系,这个关系便是皮肤契约。
Flex 4.0提供的皮肤契约主要包括3个要素:Data、Part和State,皮肤与组件之间便是通过这3个要素进行交互。
1、Data
在组件中定义可与皮肤交互的Data,无外乎使用[Bindable]关键字,这样便可以通过Skin的hostComponent获取该Data,如下代码非常明了:
//组件 private var _title:String; [Bindable] public function get title():String { return this._title; } //皮肤 <s:Label id="widgetLabel" text="{hostComponent.title}"/>
2、Part
Part其实简单理解,就是组成组件的分组件,如scrollbar,它有四个皮肤parts:即增加按钮,减少按钮,轨迹带和滚动条。如下代码表示,组件必须由一个Image组成,它通过[SkinPart]关键字标识。
//组件 [SkinPart(required="true")] public var icon:Image; //皮肤 <mx:Image id="icon"/>
通过Part不仅可以推送组件数据到皮肤中,组件也可以用它们来注册行为。定义了这些Part之后,由组件负责功能逻辑的实现,而皮肤则只负责所有可视化的内容及布局。如icon的外观表现通过Skin表示,而icon的事件监听则由组件负责。
3、State
既然事件监听可以由组件负责,当点击一个关闭按钮的时候,那该如何响应呢?我们知道:State都是定义在Skin中的,当点击关闭按钮的时候,应该响应Skin的关闭State,那么组件如何获得皮肤中的关闭State呢?这是一个问题,问题的解决方式就是通过State要素。
通常我们在组件中通过[SkinState]关键字标识皮肤中的State,如下代码。它刚好和Skin中的State对应,以表示该组件要实现Skin中的如下两种State。
//组件 [SkinState("open")] [SkinState("closed")]
关联了Skin中State之后,便可使用invalidateSkinState()和getCurrentSkinState()两个方法了。前者用于通知皮肤组件的State需要改变,这样便会调用重写的getCurrentSkinState()方法让皮肤响应该种State,进而实现了State的改变。
多数开发者在重写getCurrentSkinState()方法的时候,会创建一个状态属性,通过判断这个状态属性,设置相应的State。笔者经历了诸多项目,虽各种方法皆有,但原理大部分都是基于此方法。
如上原理虽然简单,但是却非常实用,希望能够有助于工作和学习。每天保持一份好心情,这是所有快乐工作与生活的源泉。