项目当中用到自定义ComboBox 的皮肤,因为需要显示不止一列的内容,所以打算自定义它的下拉列表。还好flex4当中自定义皮肤非常方便,你只要copy spark.skins.spark.ComboBoxSkin中的内容,稍作修改即可。
主程序:
<?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" minWidth="955" minHeight="600" xmlns:view="com.view.*"> <fx:Declarations> <!-- Place non-visual elements (e.g., services, value objects) here --> </fx:Declarations> <fx:Script> <![CDATA[ import mx.collections.ArrayList; [Bindable]public var dataProvider:ArrayList = new ArrayList([{name:"kenny",phone:123,email:"dd"}, {name:"kenny2",phone:123,email:"dd"}, {name:"kenny3",phone:123,email:"dd"}, {name:"kenny4",phone:123,email:"dd"}, {name:"kenny5",phone:123,email:"dd"}, {name:"kenny6",phone:123,email:"dd"}, {name:"kenny7",phone:123,email:"dd"}, {name:"kenny8",phone:123,email:"dd"}, {name:"kenny9",phone:123,email:"dd"}, {name:"kenny10",phone:123,email:"dd"}, {name:"kenny11",phone:123,email:"dd"}, {name:"kenny12",phone:123,email:"dd"}, {name:"kenny13",phone:123,email:"dd"}, {name:"kenny14",phone:123,email:"dd"}]); private function myLabelFunction(item:Object):String { return item ? item.name + " " + item.phone : ""; } ]]> </fx:Script> <view:CustomComboBox dataProvider="{dataProvider}" labelFunction="myLabelFunction"/> </s:Application>
自定义ComboBox:
<?xml version="1.0" encoding="utf-8"?> <s:ComboBox xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" skinClass="com.skin.CustomComboBoxSkin"> <fx:Declarations> <!-- Place non-visual elements (e.g., services, value objects) here --> </fx:Declarations> <fx:Script> <![CDATA[ import mx.collections.IList; import mx.controls.DataGrid; import mx.controls.dataGridClasses.DataGridColumn; import mx.core.IVisualElement; import mx.events.ListEvent; import spark.events.RendererExistenceEvent; private var _dataProvider:IList; private var dataProviderChanged:Boolean; [SkinPart(required="true")] public var dataGrid:DataGrid; override protected function partAdded(partName:String, instance:Object):void { super.partAdded(partName,instance); if(instance == dataGrid) { dataGrid.addEventListener(ListEvent.ITEM_CLICK,onClickHandler); dataProviderChanged = true; invalidateProperties(); } } private function dataGroup_rendererAddHandler(event:RendererExistenceEvent):void { var renderer:IVisualElement = event.renderer; if (!renderer) return; renderer.addEventListener(MouseEvent.MOUSE_DOWN, item_mouseDownHandler); } private function onClickHandler(event:ListEvent):void { selectedItem = dataGrid.selectedItem; closeDropDown(true); } override public function get dataProvider():IList { return this._dataProvider; } override public function set dataProvider(value:IList):void { this._dataProvider = value; dataProviderChanged = true; invalidateProperties(); } override protected function commitProperties():void { super.commitProperties(); if(dataProviderChanged && dataGrid) { dataProviderChanged = false; dataGrid.dataProvider = dataProvider; dataGrid.validateNow(); } } ]]> </fx:Script> </s:ComboBox>
skin 文件:
<?xml version="1.0" encoding="utf-8"?> <!-- ADOBE SYSTEMS INCORPORATED Copyright 2008 Adobe Systems Incorporated All Rights Reserved. NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms of the license agreement accompanying it. --> <!--- The default skin class for the Spark ComboBox component. The skin for the anchor button for a ComboBox component is defined by the ComboBoxButtonSkin class. The skin for the text input is defined by the ComboBoxTextInputSkin class. @see spark.components.ComboBox @see spark.skins.spark.ComboBoxButtonSkin @langversion 3.0 @playerversion Flash 10 @playerversion AIR 1.5 @productversion Flex 4 --> <s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:fb="http://ns.adobe.com/flashbuilder/2009" alpha.disabled=".5" xmlns:mx="library://ns.adobe.com/flex/mx"> <!-- host component --> <fx:Metadata> <![CDATA[ /** * @copy spark.skins.spark.ApplicationSkin#hostComponent */ [HostComponent("spark.components.ComboBox")] ]]> </fx:Metadata> <fx:Script fb:purpose="styling"> <![CDATA[ private var paddingChanged:Boolean; private var cornerRadiusChanged:Boolean; private var cornerRadius:Number = 0; /* Define the content fill items that should be colored by the "contentBackgroundColor" style. */ static private const contentFill:Array = ["bgFill"]; /** * @private */ override public function get contentItems():Array {return contentFill}; /** * @private */ override protected function commitProperties():void { super.commitProperties(); if (paddingChanged && textInput) { // Push padding styles into the textDisplay var padding:Number; padding = getStyle("paddingLeft"); if (textInput.getStyle("paddingLeft") != padding) textInput.setStyle("paddingLeft", padding); padding = getStyle("paddingTop"); if (textInput.getStyle("paddingTop") != padding) textInput.setStyle("paddingTop", padding); padding = getStyle("paddingRight"); if (textInput.getStyle("paddingRight") != padding) textInput.setStyle("paddingRight", padding); padding = getStyle("paddingBottom"); if (textInput.getStyle("paddingBottom") != padding) textInput.setStyle("paddingBottom", padding); paddingChanged = false; } if (cornerRadiusChanged) { cornerRadiusChanged = false; var cr:Number = getStyle("cornerRadius"); if (openButton) openButton.setStyle("cornerRadius", cr); if (textInput) textInput.setStyle("cornerRadius", cr); } } /** * @private */ override public function styleChanged(styleProp:String):void { var allStyles:Boolean = !styleProp || styleProp == "styleName"; super.styleChanged(styleProp); if (allStyles || styleProp.indexOf("padding") == 0) { paddingChanged = true; invalidateProperties(); } if (allStyles || styleProp == "cornerRadius") { cornerRadiusChanged = true; invalidateProperties(); } } ]]> </fx:Script> <s:states> <s:State name="normal" /> <s:State name="open" /> <s:State name="disabled" /> </s:states> <!--- The PopUpAnchor control that opens the drop-down list. <p>In a custom skin class that uses transitions, set the <code>itemDestructionPolicy</code> property to <code>none</code>.</p> --> <s:PopUpAnchor id="popUp" displayPopUp.normal="false" displayPopUp.open="true" includeIn="open" left="0" right="0" top="0" bottom="0" itemDestructionPolicy="auto" popUpPosition="below" popUpWidthMatchesAnchorWidth="true"> <!--- This includes borders, background colors, scrollers, and filters. @copy spark.components.supportClasses.DropDownListBase#dropDown --> <s:Group id="dropDown" maxHeight="134" minHeight="22" > <!-- drop shadow --> <!--- @private --> <s:RectangularDropShadow id="dropShadow" blurX="20" blurY="20" alpha="0.45" distance="7" angle="90" color="#000000" left="0" top="0" right="0" bottom="0"/> <!-- border --> <!--- @private --> <s:Rect id="border" left="0" right="0" top="0" bottom="0"> <s:stroke> <!--- @private --> <s:SolidColorStroke id="borderStroke" weight="1"/> </s:stroke> </s:Rect> <!-- fill --> <!--- Defines the appearance of drop-down list's background fill. --> <s:Rect id="background" left="1" right="1" top="1" bottom="1" > <s:fill> <!--- @private The color of the drop down's background fill. The default color is 0xFFFFFF. --> <s:SolidColor id="bgFill" color="0xFFFFFF" /> </s:fill> </s:Rect> <mx:DataGrid id="dataGrid" rowCount="6" left="0" top="0" bottom="0" right="0" hasFocusableChildren="true"> <mx:columns> <mx:DataGridColumn dataField="name" headerText="Name"/> <mx:DataGridColumn dataField="phone" headerText="Phone"/> <mx:DataGridColumn dataField="email" headerText="Email"/> </mx:columns> </mx:DataGrid> </s:Group> </s:PopUpAnchor> <!--- The default skin is ComboBoxButtonSkin. @copy spark.components.supportClasses.DropDownListBase#openButton @see spark.skins.spark.ComboBoxButtonSkin --> <s:Button id="openButton" width="19" right="0" top="0" bottom="0" focusEnabled="false" skinClass="spark.skins.spark.ComboBoxButtonSkin" /> <!--- @copy spark.components.ComboBox#textInput --> <s:TextInput id="textInput" left="0" right="18" top="0" bottom="0" skinClass="spark.skins.spark.ComboBoxTextInputSkin"/> </s:SparkSkin>
当然这只是一个简单的例子,而且你可以看到在皮肤文件中的dataGrid的column都是硬编码,在实际项目总你需要根据定义来生成这些column。