Flex4实现分组框GroupBox
文章来自:Iteye-jinxinhero
分组框(Group Box)是围绕在一组相关控件周围的带标签的矩形边框。它提供了一种通过视觉展示控件关系
的方法。如下图所示:
本文将通过以下几步来实现:
一、继承SkinnableContainer,创建组件类GroupBox。
二、声明外观部件titleDisplay用来显示组合框的标题。
三、增加title属性。
四、覆盖partAdded方法,使标题字符串能够作用于外观部件titleDisplay。
五、创建它的默认外观(皮肤)GroupBoxSkin。
六、为GroupBox增加必要样式。
---------------
一、继承SkinnableContainer,创建组件类GroupBox。
Actionscript 3.0代码
1 public class GroupBox extends SkinnableContainer 2 { 3 public function GroupBox() 4 { 5 super(); 6 } 7 }
二、声明外观部件titleDisplay用来显示组合框的标题。
Actionscript 3.0代码
1 [SkinPart(required="false")] 2 public var titleDisplay:TextBase;
三、增加title属性。
1 private var _title:String = ""; 2 [Bindable] 3 public function get title():String 4 { 5 return _title; 6 } 7 public function set title(value:String):void 8 { 9 _title = value; 10 11 if (titleDisplay) 12 titleDisplay.text = title; 13 }
四、覆盖partAdded方法,使标题字符串能够作用于外观部件titleDisplay。
1 override protected function partAdded(partName:String, instance:Object):void 2 { 3 super.partAdded(partName, instance); 4 5 if (instance == titleDisplay) 6 { 7 titleDisplay.text = title; 8 } 9 }
至此,GroupBox组件类基本创建完成,但是还不能显示。下面来创建它的默认外观(皮肤)GroupBoxSkin。
五、创建它的默认外观(皮肤)GroupBoxSkin。
第一步,创建组合框的边框。
Mxml代码
1 <!-- 边框 --> 2 <s:Rect id="border" left="0" right="0" top="10" bottom="0" 3 radiusX="4" radiusY="4"> 4 <s:stroke> 5 <s:SolidColorStroke id="borderStroke" weight="1"/> 6 </s:stroke> 7 </s:Rect>
第二步,创建外观部件titleDisplay。
1 <!-- 标题 --> 2 <s:Label id="titleDisplay" 3 maxDisplayedLines="1" 4 left="9" top="0" 5 minHeight="20" 6 verticalAlign="middle" 7 textAlign="start"/>
第三步,创建外观部件contentGroup,用于包含组合框的内容。
1 <!-- 内容区域 --> 2 <s:Group id="contentGroup" 3 left="5" right="5" top="21" bottom="5"> 4 <s:layout> 5 <s:VerticalLayout/> 6 </s:layout> 7 </s:Group>
注意,此时边框是一个闭合的矩形。
图2
从上图,可以看出现在组合框的标题文字与边框是重叠的,显然这不符合我们的要求。
为了解决这个问题,下面要为边框创建一个遮罩。
Mxml代码
1 <!-- 边框遮罩 --> 2 <s:Group id="borderGroupMask" left="0" right="0" top="0" bottom="0"> 3 <s:Rect left="0" width="7" top="0" bottom="0"> 4 <s:fill> 5 <s:SolidColor color="#ff0000" alpha="1"/> 6 </s:fill> 7 </s:Rect> 8 <s:Rect left="7" width="{titleDisplay.width+4}" top="30" bottom="0"> 9 <s:fill> 10 <s:SolidColor color="#ff0000" alpha="1"/> 11 </s:fill> 12 </s:Rect> 13 <s:Rect left="{titleDisplay.width+11}" width="100%" top="0" bottom="0"> 14 <s:fill> 15 <s:SolidColor color="#ff0000" alpha="1"/> 16 </s:fill> 17 </s:Rect> 18 </s:Group>
为<s:Rect id="border"/>增加属性:mask="{borderGroupMask}"。
六、为GroupBox增加必要样式。
第一步,在GroupBox类中增加以下样式声明,它们用来指定边框的颜色和圆角。
增加borderColor样式。
1 [Style(name="borderColor", type="uint", format="Color", inherit="no", theme="spark")] 2 [Style(name="cornerRadius", type="Number", format="Length", inherit="no", theme="spark")]
第二步,在GroupBoxSkin中覆盖updateDisplayList,把样式应用于外观。
1 override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void 2 { 3 var cr:Number = getStyle("cornerRadius"); 4 if (cornerRadius != cr) 5 { 6 cornerRadius = cr; // 取变量 7 border.topLeftRadiusX = cornerRadius; 8 border.topRightRadiusX = cornerRadius; 9 border.bottomLeftRadiusX = cornerRadius; 10 border.bottomRightRadiusX = cornerRadius; 11 } 12 13 borderStroke.color = getStyle("borderColor"); 14 borderStroke.alpha = getStyle("borderAlpha"); 15 // 16 super.updateDisplayList(unscaledWidth, unscaledHeight); 17 }
至此所有工作完成。效果如下:
图3
完整的文件如下:
1 GroupBox.as
1 package jx.components 2 { 3 import spark.components.SkinnableContainer; 4 import spark.components.supportClasses.TextBase; 5 /** 6 * The alpha of the border for this component. 7 * 8 * @default 0.5 9 * 10 * @langversion 3.0 11 * @playerversion Flash 10 12 * @playerversion AIR 1.5 13 * @productversion Flex 4 14 */ 15 [Style(name="borderAlpha", type="Number", inherit="no", theme="spark")] 16 17 /** 18 * The color of the border for this component. 19 * 20 * @default 0 21 * 22 * @langversion 3.0 23 * @playerversion Flash 10 24 * @playerversion AIR 1.5 25 * @productversion Flex 4 26 */ 27 [Style(name="borderColor", type="uint", format="Color", inherit="no", theme="spark")] 28 /** 29 * The radius of the corners for this component. 30 * 31 * @default 5 32 * 33 * @langversion 3.0 34 * @playerversion Flash 10 35 * @playerversion AIR 1.5 36 * @productversion Flex 4 37 */ 38 [Style(name="cornerRadius", type="Number", format="Length", inherit="no", theme="spark")] 39 40 public class GroupBox extends SkinnableContainer 41 { 42 public function GroupBox() 43 { 44 super(); 45 } 46 //---------------------------------- 47 // titleField 48 //---------------------------------- 49 50 [SkinPart(required="false")] 51 52 /** 53 * 定义容器中标题文本的外观的外观部件。 54 * 55 * @see jx.skins.GroupBoxSkin 56 * 57 * @langversion 3.0 58 * @playerversion Flash 10 59 * @playerversion AIR 1.5 60 * @productversion Flex 4 61 */ 62 public var titleDisplay:TextBase; 63 64 65 //---------------------------------- 66 // title 67 //---------------------------------- 68 69 /** 70 * @private 71 */ 72 private var _title:String = ""; 73 74 /** 75 * @private 76 */ 77 private var titleChanged:Boolean; 78 79 [Bindable] 80 81 /** 82 * 标题或者说明。 83 * @default "" 84 * @langversion 3.0 85 * @playerversion Flash 10 86 * @playerversion AIR 1.5 87 * @productversion Flex 4 88 */ 89 public function get title():String 90 { 91 return _title; 92 } 93 94 /** 95 * @private 96 */ 97 public function set title(value:String):void 98 { 99 _title = value; 100 101 if (titleDisplay) 102 titleDisplay.text = title; 103 } 104 override protected function partAdded(partName:String, instance:Object):void 105 { 106 super.partAdded(partName, instance); 107 108 if (instance == titleDisplay) 109 { 110 titleDisplay.text = title; 111 } 112 } 113 } 114 }
2 GroupBoxSkin.mxml
1 <?xml version="1.0" encoding="utf-8"?> 2 <s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009" 3 xmlns:mx="library://ns.adobe.com/flex/mx" 4 xmlns:s="library://ns.adobe.com/flex/spark" 5 xmlns:fb="http://ns.adobe.com/flashbuilder/2009" 6 alpha.disabled="0.5"> 7 <fx:Metadata> 8 [HostComponent("jx.components.GroupBox")] 9 </fx:Metadata> 10 11 <fx:Script fb:purpose="styling"> 12 static private const exclusions:Array = ["titleDisplay", "contentGroup"]; 13 14 /** 15 * @private 16 */ 17 override public function get colorizeExclusions():Array { 18 return exclusions; 19 } 20 21 /** 22 * @private 23 */ 24 override protected function initializationComplete():void 25 { 26 useChromeColor = true; 27 super.initializationComplete(); 28 } 29 private var cornerRadius:Number; 30 /** 31 * @private 32 */ 33 override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void 34 { 35 var cr:Number = getStyle("cornerRadius"); 36 if (cornerRadius != cr) 37 { 38 cornerRadius = cr; // 取变量 39 border.topLeftRadiusX = cornerRadius; 40 border.topRightRadiusX = cornerRadius; 41 border.bottomLeftRadiusX = cornerRadius; 42 border.bottomRightRadiusX = cornerRadius; 43 } 44 45 borderStroke.color = getStyle("borderColor"); 46 borderStroke.alpha = getStyle("borderAlpha"); 47 // 48 super.updateDisplayList(unscaledWidth, unscaledHeight); 49 } 50 </fx:Script> 51 52 <s:states> 53 <s:State name="normal" /> 54 <s:State name="disabled" /> 55 </s:states> 56 <!-- 边框遮罩 --> 57 <s:Group id="borderGroupMask" left="0" right="0" top="0" bottom="0"> 58 <s:Rect left="0" width="7" top="0" bottom="0"> 59 <s:fill> 60 <s:SolidColor color="#ff0000" alpha="1"/> 61 </s:fill> 62 </s:Rect> 63 <s:Rect left="7" width="{titleDisplay.width+4}" top="30" bottom="0"> 64 <s:fill> 65 <s:SolidColor color="#ff0000" alpha="1"/> 66 </s:fill> 67 </s:Rect> 68 <s:Rect left="{titleDisplay.width+11}" width="100%" top="0" bottom="0"> 69 <s:fill> 70 <s:SolidColor color="#ff0000" alpha="1"/> 71 </s:fill> 72 </s:Rect> 73 </s:Group> 74 <!-- 边框 --> 75 <s:Rect id="border" left="0" right="0" top="10" bottom="0" 76 radiusX="4" radiusY="4" 77 mask="{borderGroupMask}" 78 ><!--mask="{borderGroupMask}"--> 79 <s:stroke> 80 <s:SolidColorStroke id="borderStroke" weight="1"/> 81 </s:stroke> 82 </s:Rect> 83 <!-- 标题 --> 84 <s:Label id="titleDisplay" 85 maxDisplayedLines="1" 86 left="9" top="0" 87 minHeight="20" 88 verticalAlign="middle" 89 textAlign="start"/> 90 <!-- 内容区域 --> 91 <s:Group id="contentGroup" 92 left="5" right="5" top="21" bottom="5"> 93 <s:layout> 94 <s:VerticalLayout/> 95 </s:layout> 96 </s:Group> 97 </s:SparkSkin>
3 GroupBoxExam.mxml 实例文件
1 <?xml version="1.0" encoding="utf-8"?> 2 <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 3 xmlns:s="library://ns.adobe.com/flex/spark" 4 xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" xmlns:components="jx.components.*"> 5 <s:layout> 6 <s:BasicLayout/> 7 </s:layout> 8 <fx:Declarations> 9 </fx:Declarations> 10 <components:GroupBox skinClass="jx.skins.GroupBoxSkin" title="用户配置文件" cornerRadius="5"> 11 <components:layout> 12 <s:HorizontalLayout/> 13 </components:layout> 14 <s:Button/> 15 <s:Button/> 16 <s:Button/> 17 </components:GroupBox> 18 </s:Application>
4 css
可以通过css为GroupBox指定样式的默认值。
1 @namespace components "jx.components.*"; 2 components|GroupBox { 3 skinClass: ClassReference("jx.skins.GroupBoxSkin"); 4 cornerRadius: 5; 5 borderColor: #104778; 6 borderWeight: 1; 7 dropShadowVisible: false; 8 }
5 代码方式指定组件的默认CSS样式
Actionscript3.0代码
1 private static const classConstructed:Boolean = classConstruct(); 2 3 // 指定默认样式 4 private static function classConstruct():Boolean { 5 var styleManager:IStyleManager2 = FlexGlobals.topLevelApplication.styleManager; 6 if (!styleManager.getStyleDeclaration("jx.components.GroupBox")) { 7 var css:CSSStyleDeclaration = new CSSStyleDeclaration(null, styleManager); 8 css.defaultFactory = function():void { 9 this.skinClass = GroupBoxSkin; 10 this.borderAlpha = 1; 11 this.borderColor = 0; // 黑 12 // this.borderColor = 0xD3D3D3; // 灰 13 // this.borderColor = 0x104778; // 蓝 14 this.cornerRadius = 5; 15 // this.dropShadowVisible = true; 16 // this.borderWeight = 1; 17 } 18 styleManager.setStyleDeclaration("jx.components.GroupBox", css, true); 19 } 20 return true; 21 }