Study Flex《自定义组件编写过程》

使用flex也很久了,也改过别人写的flex自定义组件,可是总是会忘记一些东东。

现发现一篇记录下来。本文来自 http://wangxingrang.iteye.com/blog/1489400

一、步骤

1、重写一个组件系统依次调用Constructor(构造方法)-->createChildren()-->commitProperties()==>measure()==>updateDisplayList() ; 

a.Constructor构造方法,初始化属性,默认值 在这个方法中使用最好。

b.createChildren() 创建子对象,在组件中添加子对象。是使用addChild方法添加子对象 

c.commitProperties 用在处理属性值和更新。(多个属性值更新后统一处理入口和单值多次修改后处理入口) 

d.measure()设置组件的默认大小(以便Flex布局管理器能正确知道该组件的大小,给其分配适当空间) 

e.updateDisplayList()用来重绘组件,子对象布局逻辑等
2、添加自定义组件实际上就是将一个基本的组件的组合起来,这样的情况下就必须要重写createChildren() 和 updateDisplayList()方法

当自定义组件要对属性的变化作出反应的时候必须要重写commitProperties()方法(触发调用这个方法的是invalidateProperties) 

当自定义的组件和基类组件大小不一致的情况下就要调用measure 保证正确的大小显示。(调用invalidateSize方法)

当组件需要调整子对象全局显示逻辑,重写updateDisplayList,调用invalidateDisplayList

commitProperties   measure 和 updateDisplayList 都有自己的用处

二、例子

在下面写个例子 一个button 和 TextArea 组合的自定义组件

package cn.tsoft{
	import flash.events.Event;
	import flash.text.TextLineMetrics;	
	import mx.controls.Button;
	import mx.controls.TextArea;
	import mx.core.UIComponent;	
	/**
	 * 当子组件textArea中文件变化时,ModelText派发一个change事件
	 * 当ModelText的text属性被设置时,派发一个textChange事件
	 * 当改变Modeltext的textplacement属性后,会派发一个placementChanged事件 
	 * **/
	[Event(name="change",type="flash.events.Event")]
	[Event(name="textChanged",type="flash.events.Event")]
	[Event(name="placementChanged",type="flash.events.Event")]
	
	public class ModelText extends UIComponent{
		public function ModelText(){
			super();
		}
		
		private var text_mc:TextArea;
		private var mode_mc:Button;		
		private var bTextChanged:Boolean =false;		
		private var _text:String="ModelText";
				
		public function set text(t:String):void{
			this._text =t;
			bTextChanged = true;
			invalidateProperties();
			dispatchEvent(new Event("textChanged"));
		}
		
		
		[Bindable(event="textChanged")]
		public function get text():String{
			return text_mc.text;
		}
				
		override protected function createChildren():void{
			super.createChildren();
			if(!text_mc){
				text_mc =new TextArea();
				text_mc.explicitWidth =80;
				text_mc.editable =false;
				text_mc.addEventListener("change",handleChangeEvent);
				addChild(text_mc);
			}
			
			if(!mode_mc){
				mode_mc = new Button();
				mode_mc.label ="mylabeljieji";
				mode_mc.addEventListener("click",handleClickEvent);
				addChild(mode_mc);
			}
		}
		
		//处理有子组件派发的时间
		private function handleChangeEvent(eventObj:Event):void{
			dispatchEvent(new Event("change"));
		}
		
		private function handleClickEvent(eventObj:Event):void{
			text_mc.editable = !text_mc.editable;
		}
				
		override protected function commitProperties():void{
			super.commitProperties();
			if(bTextChanged){
				bTextChanged =false;
				text_mc.text = _text;
				invalidateDisplayList();
			}
		}
		
		/**
		 * 组建的默认宽度是文本宽度加上按钮的宽度
		 * 组件的默认高度由按钮的高度决定
		 */ 
		override protected function measure():void{
			super.measure();
			var buttonWidth:Number = mode_mc.getExplicitOrMeasuredWidth();
			var buttonHeight:Number =mode_mc.getExplicitOrMeasuredHeight();
			
			//组件默认的最小宽度和默认宽度为textArea控件的measureedWidth宽度与buttonWidth之和
			measuredWidth = measuredMinWidth =text_mc.measuredWidth+buttonWidth;
		//组件的默认高度 和最小高度问textArea 和Button 中measuredHeight中的最大值加上10个像素的边框
		    measuredHeight = measuredMinHeight = Math.max(text_mc.measuredHeight,buttonHeight)+10;
		}
				
		private var _textPlacement:String="left";
		
		public function set textPlacement(p:String):void{
			this._textPlacement = p;
			invalidateDisplayList();
			dispatchEvent(new Event("placementChanged"));
		}
		
		[Bindable(event="placementChanged")]
		public function get textPlacement():String{
			return _textPlacement;
		}
				
		/**
		 * Button控件的尺寸是Button上的label文本尺寸加上10像素的边框区域
		 * textarea控件的尺寸是组件的剩余区域,TextArea的位置取决于textPlacement属性的设置
		 * **/
		override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void{
			super.updateDisplayList(unscaledWidth,unscaledHeight);
			//为左右边框各减去1像素 , 为左右边白各减3像素
			var usableWidth:Number=unscaledWidth -8;
			//为上下边框各减去1像素 , 为上下边白各减3像素
			var usableHeight:Number = unscaledHeight -8;
			
			//根据按钮上的文本计算按钮的尺寸
			var lineMetrics:TextLineMetrics = measureText(mode_mc.label);
			//按钮文本尺寸加上10像素作为按钮的尺寸
			var buttonHeight:Number = lineMetrics.height+10;
			var buttonWidth:Number = lineMetrics.width+10;
			mode_mc.setActualSize(buttonWidth,buttonHeight);
			
			//计算文本的尺寸,允许按钮和TextArea文本之间有5个像素的间隙
			var textWidth:Number = usableWidth-buttonWidth-5;
			var textHeight:Number = usableHeight;
			text_mc.setActualSize(textWidth,textHeight);
			
			//根据textPlacement的属性确定控件的位置
			if(textPlacement == "left"){
				text_mc.move(4,4);
				mode_mc.move(4+textWidth+5,4);
			}else{
				mode_mc.move(4,4);
				text_mc.move(4+buttonWidth+5,4);
			}
			
			graphics.lineStyle(1,0xffff00,1.0);
			graphics.drawRect(0,0,unscaledWidth,unscaledHeight);
		}
	}
}

------------------------------------------------------------------


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值