9.15.编程实现组件应用皮肤

9.15.1.问题
你想更好地控制视觉元素如何在不指定图像皮肤时显示在组件中。
9.15.2.解决办法
生成一个继承mx.skins.ProgrammaticSkin 类的自定义皮肤类并重载保护类型的updateDisplayList 方法。
9.15.3.讨论
与图像皮肤相反,编程实现皮肤需要对ActionScript 更高级的理解,但提供了组件视觉表示的更深入的控制。编程实现的皮肤类是利用一些显示对象,这些对象利用绘图API 显示皮肤元素并使你能运用在指定图像皮肤时可能会打消的一些其它样式属性值。

通常来讲Flex 有两类组件:容器和控件。窗口有边框皮肤来表示显示背景,然而控件通常有一系列描述状态的皮肤(弹起、按下、经过和失效)。当然也有一些例外,如TextInput 控件使用边框皮肤。总之,在编程生成自定义皮肤之前注意组件的视觉构成是很重要的。

当为控件编程生成皮肤时你需要继承mx.skins.ProgrammaticSkin 类。当为容器生成自定义皮肤时,你需生成ProgrammaticSkin 的子类,通常也生成Border (有borderMetrics 属性)或者RectangleBorder (Border 的子类且支持背景样式)的子类。表9-1 列出Flex API 中用于编程生成自定义皮肤的基础类。

当你为自定义皮肤生成这些基类的子类时,你重载了ProgrammaticSkin 中保护类型的updateDisplayList 方法以增加基于样式属性值的绘图方法。例如:
+展开
-ActionScript
package
{
import mx.skins.ProgrammaticSkin;
public class MyCustomSkin extends ProgrammaticSkin {
public function MyCustomSkin() {}
override protected function updateDisplayList(unscaledWidth:Number,unscaledHeight:Number ):void

表9-1.Flex API 中用于编程生成自定义皮肤的基础类类用途

mx.skins.ProgrammaticSkin 所有编程实现自身的皮肤元素的基础类。
mx.skins.Border 绘制矩形和非矩形边框的基础类。包含borderMetrics 属性。
ProgrammaticSkin 的子类。
mx.skins.RectangularBorder 绘制矩形边框的基础类。Border 的子类。
支持backgroundImage、backgroundSize 和backgroundAttachment 样式。
+展开
-ActionScript
{
// grab the value for the backgroundColor style property
var backgroundColor:Number =getStyle( "backgroundColor");
// implement drawing methods.
}
}}

当每次由于更新属性而需绘制或重新绘制皮肤元素时,都要在类实例中内部调用updateDisplayList 方法。同样地在重载该方法过程中,你能够通过getStyle 方法访问样式属性并且利用绘图API 自定义显示。

你也可以通过重载measuredWidth 和measuredHeight 的只读属性,从而有选择地设置皮肤元素的默认尺寸。方法如下:
+展开
-ActionScript
package oreilly.cookbook {
import mx.skins.ProgrammaticSkin;
public class MyCustomSkin extends ProgrammaticSkin {
private var _measuredWidth:Number;
private var _measuredHeight:Number;
public function MyCustomSkin() {
_measuredWidth = 120;
_measuredHeight = 120;
}
// return defaulted constant for width
override public function get measuredWidth():Number { return _measuredWidth; }
// return defaulted constant for height
override public function get measuredHeight():Number { return _measuredHeight; }
override protected function updateDisplayList( unscaledWidth:Number, unscaledHeight:Number ):void {
// grab the value for the backgroundColor style property
var backgroundColor:Number = getStyle( "backgroundColor");
// implement drawing methods.
}
}
}

如果你不重载measuredWidth 和measuredHeight 的只读属性,它们的默认值将设为0。前面的例子中,应用编程实现皮肤类的组件将默认值设置为120 宽和120 高。尺寸可以在组件声明阶段利用width 和height 属性进行修改。

下面代码片段生成自定义边框皮肤,应用于窗口的borderSkin 样式属性:
+展开
-ActionScript
package oreilly.cookbook {
import mx.graphics.RectangularDropShadow;
import mx.skins.Border;
public class CustomBorder extends Border {
private var _dropShadow:RectangularDropShadow;
private static const CNR_RAD:Number = 5;
private static const POINT_POS:String = 'bl' ;
private static const BG_COL:uint = 0x336699;
private static const BG_ALPHA:Number = 1.0;
public function CustomBorder() {
super();
_dropShadow = new RectangularDropShadow();
}
private function getCornerRadiusObj( rad:Number,pointPos:String ):Object{
var pt:String = pointPos ? pointPos : POINT_POS;
return {tl:rad, bl:0, tr:rad, br:rad};
}
override protected function updateDisplayList( unscaledWidth:Number,unscaledHeight:Number ):void {
super.updateDisplayList(unscaledWidth, unscaledHeight );
var cornerRadius:Number = getStyle( "cornerRadius") ?getStyle( "cornerRadius") :CustomBorder.CNR_RAD;
var backgroundColor:Number = getStyle( "backgroundColor") ?getStyle( "backgroundColor"):CustomBorder.BG_COL;
var backgroundAlpha:Number =getStyle( "backgroundAlpha") ?getStyle("backgroundAlpha"):CustomBorder.BG_ALPHA;
var cnrRadius:Object = getCornerRadiusObj( cornerRadius,getStyle( "pointPosition") );
graphics.clear();
drawRoundRect( 0, 0, unscaledWidth, unscaledHeight,cnrRadius , backgroundColor, backgroundAlpha );
_dropShadow.tlRadius = cnrRadius.tl;
_dropShadow.blRadius = cnrRadius.bl;
_dropShadow.trRadius = cnrRadius.tr;
_dropShadow.brRadius = cnrRadius.br;
_dropShadow.drawShadow( graphics, 0, 0,
unscaledWidth, unscaledHeight );
}
}
}

无论何时调用updateDisplayList 方法,图像层将被清空并利用继承而得的drawRoundRect方法重新绘制。另外将应用一个阴影滤镜;这是编程实现皮肤相对图像皮肤的一个优势,因为这个技术允许你访问如滤镜等更多底层功能。

你能利用指定其它样式属性值的任一方法来应用编程实现的皮肤:嵌入地,利用setStyle 方法或者CSS。下面的例子描述了这几项技术:
+展开
-ActionScript
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical"
initialize="initHandler();">
<mx:Script>
<![CDATA[
import oreilly.cookbook.CustomBorder;
private function initHandler():void {
myVBox.setStyle( "borderSkin", CustomBorder );
}
]]>
</mx:Script>
<mx:VBox width="100" height="50"
borderSkin="oreilly.cookbook.CustomBorder" />
<mx:VBox width="50" height="20"
borderSkin="{CustomBorder}" />
<mx:VBox id="myVBox" width="80" height="20" />
</mx:Application>

当嵌入地或利用setStyle 方法应用皮肤时,你可以导入类并用它的简短名称或者利用完整的合格的类名明确皮肤。当运用简短名称来嵌入地应用皮肤类时,需要用花括号({})来求导入类的值。

利用CSS, 你需要在ClassReference 指令中明确输入完整的分类的类名。这里通过使用类型选择器将CustomBorder 皮肤应用于一个mx.containers.VBox 实例的borderSkin 属性:
+展开
-XML
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxmllayout="vertical">
<mx:Style>
VBox {
borderSkin:
ClassReference("oreilly.cookbook.CustomBorder");
cornerRadius: 30;
pointPosition: 'bl';
backgroundColor: #999933;
backgroundAlpha: 1;
paddingLeft: 5;
paddingRight: 5;
}

</mx:Style>
<mx:VBox id="myBox"
width="120height="100"
verticalAlign="middlehorizontalAlign="center">

<mx:Text text="i'm a styled VBox!textAlign="center" />
</mx:VBox>
</mx:Application>

在重载CustomBorder 中的updateDisplayList 方法时,VBox 选择中声明的其它的样式属性(cornerRadius、pointPosition 等等) 用于自定义显示VBox 实例的背景内容。

加支付宝好友偷能量挖...


评论(0)网络
阅读(98)喜欢(0)flash/flex/fcs/AIR