flex – 自定义复合控件在添加回VGROUP后仅在0.5-1秒内无法正确
我正在远离MXML并在ActionScript中构建了一个自定义组件控件.
我正确显示控件.我从显示列表中删除它并使用.addElement(control)方法再次将其添加回来之后出现问题. 这是再次添加它的代码. private function displayParameters(parameters:ArrayCollection):void{ for(var index:int = 0; index<parameters.length; index++){ if(parameters[index] is ReportControl){ var control:ReportControl = parameters[index] as ReportControl; control.percentWidth = 100; vgParameters.addElement(control); } } } ReportControl是comboBoxMultiSelect的基类,如下所示. ReportControl没有任何图形特殊的内容,它只是作为其具体实现(多态)的编程接口. public class comboBoxMultiSelect extends ReportControl{ [Embed("../Assets/Icons/plus-16.png")] private var plusIcon:Class; [Embed("../Assets/Icons/minus-16.png")] private var minusIcon:Class; private var expanded:Boolean = false; private var buttonIconChanged:Boolean = false; private var _drp:ComboBox; private var _btnMultiple:Button; private var _horizontalGroup:HGroup; private var _multiSelector:ReportGridSelector; private var _multiSelection:Boolean = true; private var bMultiSelectionChanged:Boolean = false; public function ToggleExpanded():void{ expanded = !_expanded; buttonIconChanged = true; invalidateSize(); invalidateProperties(); invalidateDisplayList(); } public function comboBoxMultiSelect(){ super(); } override protected function createChildren():void{ super.createChildren(); if(!_horizontalGroup){ _horizontalGroup = new HGroup(); _horizontalGroup.gap = 0; _horizontalGroup.percentWidth = 100; _horizontalGroup.height = ReportControl.SIZE_DEFAULT_HEIGHT; addChild(_horizontalGroup); } if(!_drp){ _drp = new ComboBox(); _drp.text = GuiText; _drp.percentWidth = 100; _drp.height = ReportControl.SIZE_DEFAULT_HEIGHT; _horizontalGroup.addElement(_drp); } if(!_btnMultiple && _multiSelection){ _btnMultiple = new Button; _btnMultiple.setStyle("icon",plusIcon); _btnMultiple.width = 20; _btnMultiple.height = ReportControl.SIZE_DEFAULT_HEIGHT; _btnMultiple.visible = true; _btnMultiple.addEventListener(MouseEvent.CLICK,function(event:MouseEvent):void{ ToggleExpanded(); }); _horizontalGroup.addElement(_btnMultiple); } } override protected function commitProperties():void{ super.commitProperties(); if(buttonIconChanged){ if(_expanded==true){ _btnMultiple.setStyle("icon",minusIcon); } else{ _btnMultiple.setStyle("icon",plusIcon); } buttonIconChanged = false; } } override protected function updateDisplayList(unscaledWidth:Number,unscaledHeight:Number):void{ super.updateDisplayList(unscaledWidth,unscaledHeight); _horizontalGroup.width = unscaledWidth; _horizontalGroup.height = unscaledHeight; } override protected function measure():void{ super.measure(); measuredMinWidth = measuredWidth = ReportControl.SIZE_DEFAULT_WIDTH; //minimum size //default size if(_expanded==true) measuredMinHeight= measuredHeight = 200; else measuredMinHeight= measuredHeight = ReportControl.SIZE_DEFAULT_HEIGHT; } } 当我使用vgParameters.addElement(control)添加控件时,comboBoxMultiSelect无法正确呈现.按钮_btnMultiple内的plusIcon最初没有正确定位,但随后在0.5-1秒之后快速纠正. 我很确定问题出在comboBoxMultiSelect中,只是不确定如何强制图标保持在同一个地方. 在我辛勤工作之后,这是非常烦人的,任何人都有关于我做错了什么的想法? 谢谢 :) 更新—–>这是ReportControl代码 [Event (name= "controlChanged",type="Reporting.ReportControls.ReportControlEvent")] [Event (name= "controlIsNowValid",type="Reporting.ReportControls.ReportControlEvent")] public class ReportControl extends UIComponent { private var _guiText:String; private var _amfPHPArgumentName:String; private var _reportResult:ReportResult; private var _sequence:int; private var _reportId:int; private var _controlConfiguration:ReportParameterVO; private var _isValid:Boolean = false; internal var _selection:Object; /** * SIZE_DEFAULT_HEIGHT = 22 */ internal static const SIZE_DEFAULT_HEIGHT:int = 22; /** * SIZE_DEFAULT_WIDTH = 150 */ internal static const SIZE_DEFAULT_WIDTH:int = 150; public function get ControlConfiguration():ReportParameterVO{ return _controlConfiguration; } public function set ControlConfiguration(value:ReportParameterVO):void{ _controlConfiguration = value; _guiText = (value ? value.GuiText:""); _amfPHPArgumentName = (value ? value.AMFPHP_ArgumentName: ""); _sequence = (value ? value.Sequence : null); _reportId = (value ? value.ReportId : null); } public function get IsValid():Boolean{ return _isValid; } public function get ReportID():int{ return _reportId; } public function get Sequence():int{ return _sequence; } public function get ControlRepResult():ReportResult{ return _reportResult; } public function set ControlRepResult(value:ReportResult):void{ _reportResult = value; } internal function set Selection(value:Object):void{ _selection = value; } internal function get Selection():Object{ return _selection; } public function get ParameterSelection():Object{ return _selection; } public function get GuiText():String{ return _guiText; } public function get AmfPHPArgumentName():String{ return _amfPHPArgumentName; } public function ReportControl(){ //TODO: implement function super(); } public function dispatchControlChanged():void{ this.dispatchEvent(new ReportControlEvent(ReportControlEvent.CONTROL_CHANGED,this,true)); } public function dispatchControlIsNowValid():void{ this.dispatchEvent(new ReportControlEvent(ReportControlEvent.CONTROL_IS_NOW_VALID,true)); } public function addSelfToValueObject(valueObject:Object):Object{ valueObject[AmfPHPArgumentName] = _selection; return valueObject; } } 解决方法
我将尝试举例说明我们在上面的评论中讨论过的Spark皮肤架构的含义.这不是你问题的直接答案,但我认为你可能会发现它很有趣.为了简洁起见,我将不得不使它比你的组件更简单,因为你似乎已经删除了一些问题的代码,所以我无法确切地知道它应该做什么.
这将是一个组件,通过单击按钮,您可以在正常状态和展开状态之间切换.首先,我们将创建皮肤类.通常,您首先要创建主机组件,但这样解释起来会更容易. <!-- my.skins.ComboBoxMultiSelectSkin --> <s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" height.normal="25" height.expanded="200"> <fx:Metadata> [HostComponent("my.components.ComboBoxMultiSelect")] </fx:Metadata> <s:states> <s:State name="normal" /> <s:State name="expanded" /> </s:states> <s:layout> <s:HorizontalLayout gap="0" /> </s:layout> <s:ComboBox id="comboBox" width="100%" /> <s:Button id="toggleButton" width="20" icon.normal="@Embed('../Assets/Icons/plus-16.png')" icon.expanded="@Embed('../Assets/Icons/minus-16.png')"/> </s:Skin> 因此,我们完全设置了组件的外观和布局方式.你觉得你的头痛消失了吗?我觉得这很优雅.我们有两个状态,组件的高度将调整为当前选择的状态,按钮的图标也是如此.切换状态的方式和时间是组件行为,并将在主机组件中定义. 现在让我们用普通的ActionScript创建该主机组件.为此,我们将扩展SkinnableComponent(请注意,如果扩展SkinnableComponent而不是UIComponent,它也可以扩展ReportControl). [SkinState("normal")] [SkinState("expanded")] public class ComboBoxMultiSelect extends SkinnableComponent { [SkinPart(required="true")] public var toggleButton:IEventDispatcher; [SkinPart(required="true")] public var comboBox:ComboBox; private var expanded:Boolean; override protected function partAdded(partName:String,instance:Object):void { super.partAdded(partName,instance); switch (instance) { case toggleButton: toggleButton.addEventListener(MouseEvent.CLICK,handleToggleButtonClick); break; case comboBox: comboBox.addEventListener(IndexChangeEvent.CHANGE,handleComboSelection); break; } } private function handleToggleButtonClick(event:MouseEvent):void { toggleExpanded(); } private function handleComboSelection(event:IndexChangeEvent):void { //handle comboBox selection } protected function toggleExpanded():void { expanded = !expanded; invalidateSkinState(); } override protected function getCurrentSkinState():String { return expanded ? "expanded" : "normal"; } } 好吧,这里还有很多事情要做. >首先查看SkinState元数据声明:当为组件分配外观类时,编译器将检查该外观是否已实现所需的状态. Etvoilà!你有一个工作组件,行为很好地分成了actionscript类,你不必担心布局错综复杂.如果您希望创建具有相同行为的组件,但它应该水平扩展而不是垂直扩展:只需创建一个调整宽度而不是高度的新外观,并将其分配给同一主机组件. 等一下!我差点忘了告诉你如何将皮肤分配给组件.你可以内联: <c:ComboBoxMultiSelect skinClass="my.skins.ComboBoxMultiSelectSkin" /> 或通过造型: @namespace c "my.components.*"; c|ComboBoxMultiSelect { skinClass: ClassReference("my.skins.ComboBoxMultiSelectSkin") } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |