Flex4 - 通过继承UIComponent来创建自定义组件
作者:hangge | 2015-02-04 09:21
通过继承UIComponent来创建自定义组件,可以获得更好的性能。继承UIComponent的组件一般要覆盖重写createChildren(), measure(), commitProperties(), updateDisplayList(), styleChanged()等方法。
下面一个样例通过一个自定义一个图例标签组件来演示实现方法。

--- 使用 ---
下面一个样例通过一个自定义一个图例标签组件来演示实现方法。
效果图:

--- 自定义组件 IconLabel.as ---
package yu
{
import flash.display.DisplayObject;
import mx.core.UIComponent;
import spark.components.Label;
/**
* 前面一个图标,后面是label的组件
* -------------------------------------
* 失效方法 ---> 生效方法
* invalidateProperties() commitProperties()
* invalidateSize() measure()
* invalidateDisplayList() updateDisplayList()
*/
/**
* 元数据标记指定自定义样式(图标与label的间距,并禁用样式继承)
*/
[Style(name="horizontalGap",type="int",inheriting="false")]
public class IconLabel extends UIComponent
{
/**
* 正确图标
*/
[Embed(source="Success.png")]
private var IconSuccess:Class;
/**
* 错误图标
*/
[Embed(source="Error.png")]
private var IconError:Class;
/**
* 当前图标
*/
private var currentIcon:DisplayObject;
/**
* 文本标签
*/
private var displayLabel:Label;
/**
* 文本标签显示的文字
*/
private var _label:String;
/**
* 文本标签显示文字状态是否改变。(避免每次调用commitProperties()方法的时候吧所有的属性都重新赋值一边)
*/
private var labelChanged:Boolean = false;
/**
* 设置文本标签显示的文字,并调用对应的失效方法
*/
public function set label(value:String):void{
this._label = value;
this.labelChanged = true;
//并不直接对displayLabel赋值,而是将所有的更新合并到一起,到下一帧生效,节约资源
invalidateProperties();
invalidateSize();
}
/**
* 成功状态
*/
public static const STATUS_SUCCESS:String = "success";
/**
* 失败状态
*/
public static const STATUS_ERROR:String = "error";
/**
* 当前状态
*/
private var _status:String;
/**
* 状态是否改变。(避免每次调用commitProperties()方法的时候吧所有的属性都重新赋值一边)
*/
private var statusChanged:Boolean = false;
/**
* 设置状态.
* 并增加了绑定,使这个组件属性可以绑定
*/
[Bindable]
public function set status(value:String):void{
this._status = value;
this.statusChanged = true;
invalidateProperties();
}
/**
* 获取状态.
*/
public function get status():String{
return this._status;
}
/**
* 获取间距样式。如果未设置就返回5
*/
private function get horizontalGapDefault():int{
var horizontalGap:Number = getStyle("horizontalGap");
return (horizontalGap == undefined) ? 5 : horizontalGap;
}
/**
* 构造函数
*/
public function IconLabel()
{
super();
}
/**
* 创建组建对象
*/
override protected function createChildren():void{
super.createChildren();
//创建添加图标
if(this.currentIcon == null){
this.currentIcon = new IconSuccess();
}
addChild(this.currentIcon);
//创建添加文本标签
if(this.displayLabel == null){
this.displayLabel = new Label();
this.displayLabel.setStyle("verticalAlign","middle");
//this.displayLabel.setStyle("paddingBottom","-5");
}
addChild(this.displayLabel);
}
/**
* 更新组件属性
* invalidateProperties()失效方法被调用时此方法会调用
*/
override protected function commitProperties():void{
super.commitProperties();
//更新标签
if(this.labelChanged){
//当值被提交时重置为false;
this.labelChanged = false;
this.displayLabel.text = this._label;
}
//更新图标
if(this.statusChanged){
this.statusChanged = false;
removeChild(this.currentIcon);
switch(this._status){
case STATUS_SUCCESS:
this.currentIcon = new IconSuccess();
break;
case STATUS_ERROR:
this.currentIcon = new IconError();
break;
}
addChild(this.currentIcon);
}
}
/**
* 确定组件最佳尺寸和可选的最小尺寸
* invalidateSize()失效方法被调用时此方法会调用
*/
override protected function measure():void{
super.measure();
//对于没有继承UIComponent的子对象:使用width和height获取大小
//对于继承UIComponent的子对象:
//使用getExplicitOrMeasuredWidth()和getExplicitOrMeasuredHeight()获取大小
this.measuredHeight = this.measuredMinHeight
= Math.max(this.currentIcon.height, this.displayLabel.getExplicitOrMeasuredHeight());
this.measuredWidth = this.measuredMinWidth
= this.currentIcon.width + this.horizontalGapDefault
+ this.displayLabel.getExplicitOrMeasuredWidth();
}
/**
* 布局组件的内容,并执行任何所需的绘制和重绘
* invalidateSize()失效方法被调用时此方法会调用
*/
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void{
super.updateDisplayList(unscaledWidth,unscaledHeight);
this.currentIcon.y = (unscaledHeight-this.currentIcon.height)/2;
//对于继承UIComponent的子对象:使用Move()来定位,使用setActualSize()来决定尺寸
this.displayLabel.move(
this.currentIcon.x + this.currentIcon.width + this.horizontalGapDefault, 0
);
this.displayLabel.setActualSize(
unscaledWidth-this.currentIcon.width - this.horizontalGapDefault, unscaledHeight
);
}
/**
* 样式改变执行任何所需的绘制和重绘
*/
override public function styleChanged(styleProp:String):void{
super.styleChanged(styleProp);
if(styleProp == "horizontalGap"){
invalidateSize();
invalidateDisplayList();
}
}
}
}
--- 使用 ---
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
creationComplete="init()"
xmlns:yu="yu.*"
fontFamily="微软雅黑" fontSize="20">
<fx:Script>
<![CDATA[
private function init():void{
var iconLabel:IconLabel = new IconLabel();
iconLabel.label = "失败啦";
iconLabel.status = IconLabel.STATUS_ERROR;
iconLabel.setStyle("horizontalGap",15);
this.addElement(iconLabel);
}
]]>
</fx:Script>
<s:layout>
<s:VerticalLayout paddingLeft="20" paddingTop="30"/>
</s:layout>
<yu:IconLabel label="成功啦" status="{IconLabel.STATUS_SUCCESS}" />
</s:Application>
全部评论(0)