发布标准FLEX库项目
本文将介绍如何发布标准FLEX库项目,其中包括:
自定义组件(包含分离的皮肤文件)
自定义组件库的namespace
使用defaults.css指定组件皮肤
首先,打开FlashBuilder,创建一个flex库项目,名称随便取,如下图
下面开始主要任务:
自定义组件
创建Version.as
在vision.core包下创建名为Version.as的actionscript文件,里面只有一句public static const VERSION:String = “1.0.0”;
此文件在其他类中使用include方式引入,定义组件的版本号。
创建LabelInput类
在vision.components包下创建名为LabelInput的类,并继承自SkinableComponent,为LabelInput创建相关属性,并补全代码,如下package vision.components { import flash.events.Event; import spark.components.Label; import spark.components.TextInput; import spark.components.supportClasses.SkinnableComponent; import spark.events.TextOperationEvent; [SkinState("normal")] [SkinState("disabled")] public class LabelInput extends SkinnableComponent { include "../core/Version.as" public function LabelInput() { super(); } override protected function commitProperties():void { super.commitProperties(); if (_labelChanged) { _labelChanged = false; if (labelDisplay != null) labelDisplay.text = _label; } if (_textChanged) { _textChanged = false; if (textInput != null) textInput.text = _text; } if (_promptChanged) { _promptChanged = false; if (textInput != null) textInput.prompt = _prompt; } } override protected function getCurrentSkinState():String { return enabled ? "normal" : "disabled"; } override protected function partAdded(partName:String, instance:Object) : void { super.partAdded(partName, instance); if (instance == labelDisplay) { labelDisplay.text = label; } if (instance == textInput) { textInput.text = text; textInput.prompt = prompt; textInput.addEventListener(TextOperationEvent.CHANGE, textInput_changeHandler, false, 0, true); } } override protected function partRemoved(partName:String, instance:Object) : void { super.partRemoved(partName, instance); if (instance == textInput) { textInput.removeEventListener(TextOperationEvent.CHANGE, textInput_changeHandler, false); } } private function textInput_changeHandler($event:TextOperationEvent):void { _text = textInput.text; dispatchEvent(new Event("textChanged")); } private var _label:String; private var _labelChanged:Boolean; [Bindable("labelChanged")] /** * Label标签。 */ public function get label():String { return _label; } public function set label($value:String):void { if (_label != $value) { _label = $value; _labelChanged = true; invalidateProperties(); dispatchEvent(new Event("labelChanged")); } } private var _text:String; private var _textChanged:Boolean; [Bindable("textChanged")] /** * 输入文本。 */ public function get text():String { return _text; } public function set text($value:String):void { if (_text != $value) { _text = $value; _textChanged = true; invalidateProperties(); dispatchEvent(new Event("textChanged")); } } private var _prompt:String; private var _promptChanged:Boolean; [Bindable("promptChanged")] /** * 文本框提示。 */ public function get prompt():String { return _prompt; } public function set prompt($value:String):void { if (_prompt != $value) { _prompt = $value; _promptChanged = true; invalidateProperties(); dispatchEvent(new Event("promptChanged")); } } [SkinPart(required="false")] /** * 定义Label属性的显示标签皮肤组件。 */ public var labelDisplay:Label; [SkinPart(required="true")] /** * 定义Label属性的显示标签皮肤组件。 */ public var textInput:TextInput; } }
这里有几点需要注意
- [SkinState]
此标签用于定义皮肤状态,该组件包含2种状态,normal与disabled,我们可以通过enabled属性来控制它是否为可用状态,此业务逻辑在getCurrentSkinState方法中实现。 - [SkinPart(required=”false”)]
此标签用于定义皮肤的子元件,required为true时决定该子元件在皮肤中必须定义。 - [Bindable(“labelChanged”)]
此标签用于定义该属性绑定的事件,当labelChanged事件派发时,如果此时有其他元素的属性被绑定到该label值上,会跟随label的改变而改变。 - createChildren, commitProperties, measure, updateDisplayList
这些方法为自定义FLEX组件的最经常需要覆盖的方法,如果不太明白这些方法的原理,建议去阅读一下关于FLEX生命周期的文章。 - include
使用include语法引入文件时,如果不取消对引入文件的语法检查,会把引入文件当做一个类来处理,这样就会引发编译器错误,需要在库项目的属性面板做如下配置
- [SkinState]
创建LabelInputSkin
在vision.skins包下创建LabelInputSkin mxml外观
主机组件为LabelInput
LabelInputSkin完整代码如下:<?xml version="1.0" encoding="utf-8"?> <s:Skin minWidth="40" minHeight="21" alpha.disabled=".5" 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> <![CDATA[ [HostComponent("vision.components.LabelInput")] ]]> </fx:Metadata> <!-- states --> <s:states> <s:State name="normal" /> <s:State name="disabled" /> </s:states> <s:layout> <s:HorizontalLayout verticalAlign="middle"/> </s:layout> <s:Label id="labelDisplay"/> <s:TextInput id="textInput"/> </s:Skin>
这里定义的皮肤子元素labelDisplay和textInput在LabelInput组件中都有定义为SkinPart,其中labelDisplay可以删除,因为在LabelInput中,该皮肤元件的required为false。
至此我们自定义组件部分就已经完成。
自定义组件库的namespace
创建design
在src目录下创建design.xml,内容如下:<design> <namespaces> <namespace prefix="vs" uri="http://www.vision.com/flex" /> </namespaces> <categories> <category id="vsComponents" label="VS Components" defaultExpand="true" /> </categories> <components> <component name="LabelInput" namespace="vs" category="vsComponents" insertStyle="control"> </component> </components> </design>
注意这里namespace即为明明空间的定义,prefix为前缀,在mxml中的写法即为:
xmlns:vs="http://www.vision.com/flex"
category定义在组件面板中的分类,component定义具体组件。创建mainfest清单
在src目录下创建vs-mainfest.xml,注意这里前面的vs必须与在design.xml中配置的namespace的prefix的值相同,否则不能识别为vs,vs-mainfest.xml内容如下:<componentPackage> <component id="LabelInput" class="vision.components.LabelInput"/> </componentPackage>
这里将所有自定义的组件集合写在此处。
- 编译器配置
在项目属性的FLEX库编译器中配置命名空间和清单文件:
到这一步之后,需要重启一下Flash Builder,才能使命名空间生效。
使用defaults.css指定组件皮肤
创建defaults.css
在src目录下创建defaults.css,内容如下:@namespace s "library://ns.adobe.com/flex/spark"; @namespace mx "library://ns.adobe.com/flex/mx"; @namespace vs "vision.components.*"; vs|LabelInput { skinClass : ClassReference("vision.skins.LabelInputSkin"); }
添加编译参数
项目属性面板-Flex库编译器-附加的编译参数中加入-include-file=defaults.css,defaults.css
至此,标准FLEX库项目已经配置完成,可新建一个测试项目引入库项目并测试。