原文地址:http://www.iteye.com/topic/773679
分组框(Group Box)是围绕在一组相关控件周围的带标签的矩形边框。它提供了一种通过视觉展示控件关系
的方法。如下图所示:
本文将通过以下几步来实现:
一、继承SkinnableContainer,创建组件类GroupBox。
二、声明外观部件titleDisplay用来显示组合框的标题。
三、增加title属性。
四、覆盖partAdded方法,使标题字符串能够作用于外观部件titleDisplay。
五、创建它的默认外观(皮肤)GroupBoxSkin。
六、为GroupBox增加必要样式。
---------------
一、继承SkinnableContainer,创建组件类GroupBox。
- public class GroupBox extends SkinnableContainer
- {
- public function GroupBox()
- {
- super();
- }
- }
二、声明外观部件titleDisplay用来显示组合框的标题。
- [SkinPart(required="false")]
- public var titleDisplay:TextBase;
三、增加title属性。
- private var _title:String = "";
- [Bindable]
- public function get title():String
- {
- return _title;
- }
- public function set title(value:String):void
- {
- _title = value;
- if (titleDisplay)
- titleDisplay.text = title;
- }
四、覆盖partAdded方法,使标题字符串能够作用于外观部件titleDisplay。
- override protected function partAdded(partName:String, instance:Object):void
- {
- super.partAdded(partName, instance);
- if (instance == titleDisplay)
- {
- titleDisplay.text = title;
- }
- }
至此,GroupBox组件类基本创建完成,但是还不能显示。下面来创建它的默认外观(皮肤)GroupBoxSkin。
五、创建它的默认外观(皮肤)GroupBoxSkin。
第一步,创建组合框的边框。
- <!-- 边框 -->
- <s:Rect id="border" left="0" right="0" top="10" bottom="0"
- radiusX="4" radiusY="4"
- >
- <s:stroke>
- <s:SolidColorStroke id="borderStroke" weight="1"/>
- </s:stroke>
- </s:Rect>
第二步,创建外观部件titleDisplay。
- <!-- 标题 -->
- <s:Label id="titleDisplay"
- maxDisplayedLines="1"
- left="9" top="0"
- minHeight="20"
- verticalAlign="middle"
- textAlign="start"/>
第三步,创建外观部件contentGroup,用于包含组合框的内容。
- <!-- 内容区域 -->
- <s:Group id="contentGroup"
- left="5" right="5" top="21" bottom="5">
- <s:layout>
- <s:VerticalLayout/>
- </s:layout>
- </s:Group>
注意,此时边框是一个闭合的矩形。
图2
从上图,可以看出现在组合框的标题文字与边框是重叠的,显然这不符合我们的要求。
为了解决这个问题,下面要为边框创建一个遮罩。
- <!-- 边框遮罩 -->
- <s:Group id="borderGroupMask" left="0" right="0" top="0" bottom="0">
- <s:Rect left="0" width="7" top="0" bottom="0">
- <s:fill>
- <s:SolidColor color="#ff0000" alpha="1"/>
- </s:fill>
- </s:Rect>
- <s:Rect left="7" width="{titleDisplay.width+4}" top="30" bottom="0">
- <s:fill>
- <s:SolidColor color="#ff0000" alpha="1"/>
- </s:fill>
- </s:Rect>
- <s:Rect left="{titleDisplay.width+11}" width="100%" top="0" bottom="0">
- <s:fill>
- <s:SolidColor color="#ff0000" alpha="1"/>
- </s:fill>
- </s:Rect>
- </s:Group>
为<s:Rect id="border"/>增加属性:mask="{borderGroupMask}"。
六、为GroupBox增加必要样式。
第一步,在GroupBox类中增加以下样式声明,它们用来指定边框的颜色和圆角。
增加borderColor样式。
- [Style(name="borderColor", type="uint", format="Color", inherit="no", theme="spark")]
- [Style(name="cornerRadius", type="Number", format="Length", inherit="no", theme="spark")]
第二步,在GroupBoxSkin中覆盖updateDisplayList,把样式应用于外观。
- override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
- {
- var cr:Number = getStyle("cornerRadius");
- if (cornerRadius != cr)
- {
- cornerRadius = cr; // 取变量
- border.topLeftRadiusX = cornerRadius;
- border.topRightRadiusX = cornerRadius;
- border.bottomLeftRadiusX = cornerRadius;
- border.bottomRightRadiusX = cornerRadius;
- }
- borderStroke.color = getStyle("borderColor");
- borderStroke.alpha = getStyle("borderAlpha");
- //
- super.updateDisplayList(unscaledWidth, unscaledHeight);
- }
至此所有工作完成。效果如下:
图3
完整的文件如下:
1 GroupBox.as
- package jx.components
- {
- import spark.components.SkinnableContainer;
- import spark.components.supportClasses.TextBase;
- /**
- * The alpha of the border for this component.
- *
- * @default 0.5
- *
- * @langversion 3.0
- * @playerversion Flash 10
- * @playerversion AIR 1.5
- * @productversion Flex 4
- */
- [Style(name="borderAlpha", type="Number", inherit="no", theme="spark")]
- /**
- * The color of the border for this component.
- *
- * @default 0
- *
- * @langversion 3.0
- * @playerversion Flash 10
- * @playerversion AIR 1.5
- * @productversion Flex 4
- */
- [Style(name="borderColor", type="uint", format="Color", inherit="no", theme="spark")]
- /**
- * The radius of the corners for this component.
- *
- * @default 5
- *
- * @langversion 3.0
- * @playerversion Flash 10
- * @playerversion AIR 1.5
- * @productversion Flex 4
- */
- [Style(name="cornerRadius", type="Number", format="Length", inherit="no", theme="spark")]
- public class GroupBox extends SkinnableContainer
- {
- public function GroupBox()
- {
- super();
- }
- //----------------------------------
- // titleField
- //----------------------------------
- [SkinPart(required="false")]
- /**
- * 定义容器中标题文本的外观的外观部件。
- *
- * @see jx.skins.GroupBoxSkin
- *
- * @langversion 3.0
- * @playerversion Flash 10
- * @playerversion AIR 1.5
- * @productversion Flex 4
- */
- public var titleDisplay:TextBase;
- //----------------------------------
- // title
- //----------------------------------
- /**
- * @private
- */
- private var _title:String = "";
- /**
- * @private
- */
- private var titleChanged:Boolean;
- [Bindable]
- /**
- * 标题或者说明。
- * @default ""
- * @langversion 3.0
- * @playerversion Flash 10
- * @playerversion AIR 1.5
- * @productversion Flex 4
- */
- public function get title():String
- {
- return _title;
- }
- /**
- * @private
- */
- public function set title(value:String):void
- {
- _title = value;
- if (titleDisplay)
- titleDisplay.text = title;
- }
- override protected function partAdded(partName:String, instance:Object):void
- {
- super.partAdded(partName, instance);
- if (instance == titleDisplay)
- {
- titleDisplay.text = title;
- }
- }
- }
- }
2 GroupBoxSkin.mxml
- <?xml version="1.0" encoding="utf-8"?>
- <s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009"
- xmlns:mx="library://ns.adobe.com/flex/mx"
- xmlns:s="library://ns.adobe.com/flex/spark"
- xmlns:fb="http://ns.adobe.com/flashbuilder/2009"
- alpha.disabled="0.5">
- <fx:Metadata>
- [HostComponent("jx.components.GroupBox")]
- </fx:Metadata>
- <fx:Script fb:purpose="styling">
- static private const exclusions:Array = ["titleDisplay", "contentGroup"];
- /**
- * @private
- */
- override public function get colorizeExclusions():Array {
- return exclusions;
- }
- /**
- * @private
- */
- override protected function initializationComplete():void
- {
- useChromeColor = true;
- super.initializationComplete();
- }
- private var cornerRadius:Number;
- /**
- * @private
- */
- override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
- {
- var cr:Number = getStyle("cornerRadius");
- if (cornerRadius != cr)
- {
- cornerRadius = cr; // 取变量
- border.topLeftRadiusX = cornerRadius;
- border.topRightRadiusX = cornerRadius;
- border.bottomLeftRadiusX = cornerRadius;
- border.bottomRightRadiusX = cornerRadius;
- }
- borderStroke.color = getStyle("borderColor");
- borderStroke.alpha = getStyle("borderAlpha");
- //
- super.updateDisplayList(unscaledWidth, unscaledHeight);
- }
- </fx:Script>
- <s:states>
- <s:State name="normal" />
- <s:State name="disabled" />
- </s:states>
- <!-- 边框遮罩 -->
- <s:Group id="borderGroupMask" left="0" right="0" top="0" bottom="0">
- <s:Rect left="0" width="7" top="0" bottom="0">
- <s:fill>
- <s:SolidColor color="#ff0000" alpha="1"/>
- </s:fill>
- </s:Rect>
- <s:Rect left="7" width="{titleDisplay.width+4}" top="30" bottom="0">
- <s:fill>
- <s:SolidColor color="#ff0000" alpha="1"/>
- </s:fill>
- </s:Rect>
- <s:Rect left="{titleDisplay.width+11}" width="100%" top="0" bottom="0">
- <s:fill>
- <s:SolidColor color="#ff0000" alpha="1"/>
- </s:fill>
- </s:Rect>
- </s:Group>
- <!-- 边框 -->
- <s:Rect id="border" left="0" right="0" top="10" bottom="0"
- radiusX="4" radiusY="4"
- mask="{borderGroupMask}"
- ><!--mask="{borderGroupMask}"-->
- <s:stroke>
- <s:SolidColorStroke id="borderStroke" weight="1"/>
- </s:stroke>
- </s:Rect>
- <!-- 标题 -->
- <s:Label id="titleDisplay"
- maxDisplayedLines="1"
- left="9" top="0"
- minHeight="20"
- verticalAlign="middle"
- textAlign="start"/>
- <!-- 内容区域 -->
- <s:Group id="contentGroup"
- left="5" right="5" top="21" bottom="5">
- <s:layout>
- <s:VerticalLayout/>
- </s:layout>
- </s:Group>
- </s:SparkSkin>
3 GroupBoxExam.mxml 实例文件
- <?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:components="jx.components.*">
- <s:layout>
- <s:BasicLayout/>
- </s:layout>
- <fx:Declarations>
- </fx:Declarations>
- <components:GroupBox skinClass="jx.skins.GroupBoxSkin" title="用户配置文件" cornerRadius="5">
- <components:layout>
- <s:HorizontalLayout/>
- </components:layout>
- <s:Button/>
- <s:Button/>
- <s:Button/>
- </components:GroupBox>
- </s:Application>
4 css
可以通过css为GroupBox指定样式的默认值。
- @namespace components "jx.components.*";
- components|GroupBox {
- skinClass: ClassReference("jx.skins.GroupBoxSkin");
- cornerRadius: 5;
- borderColor: #104778;
- borderWeight: 1;
- dropShadowVisible: false;
- }
5 代码方式指定组件的默认CSS样式
- private static const classConstructed:Boolean = classConstruct();
- // 指定默认样式
- private static function classConstruct():Boolean {
- var styleManager:IStyleManager2 = FlexGlobals.topLevelApplication.styleManager;
- if (!styleManager.getStyleDeclaration("jx.components.GroupBox")) {
- var css:CSSStyleDeclaration = new CSSStyleDeclaration(null, styleManager);
- css.defaultFactory = function():void {
- this.skinClass = GroupBoxSkin;
- this.borderAlpha = 1;
- this.borderColor = 0; // 黑
- // this.borderColor = 0xD3D3D3; // 灰
- // this.borderColor = 0x104778; // 蓝
- this.cornerRadius = 5;
- // this.dropShadowVisible = true;
- // this.borderWeight = 1;
- }
- styleManager.setStyleDeclaration("jx.components.GroupBox", css, true);
- }
- return true;
- }
完整的项目请下载附件GroupBoxExam.zip。