您的位置:首页 > 其它

关于Spark皮肤

2010-04-29 13:58 176 查看
Flex4Spark皮肤
在Flex4skinning模型中,皮肤控制器包括布局一个组件的所有可视元素。新的体系结构使开发人员能更好地控制其组件的皮肤,就像一些结构化的易用工具的工作方式。以前,MX组件使用Helo主题作为它们的皮肤,其皮肤主要通过样式属性来进行指定。

Spark皮肤可以包含多个对象如图形元素、文本、图像和过场变化。皮肤支持状态,以便组件的状态更改时,皮肤也变化。皮肤状态和过程转换很好的进行了整合,以便你可以对皮肤的一个或多个部件添加效果而无需添加太多的代码。

在MXML中,你通常写Spark皮肤类。你可以用来绘制该图形的元素的MXML图形标记(或FXG组件),并使用MXML或ActionScript设定子组件。

Flex4皮肤的基类是spark.components.supportClasses.Skin。默认Spark皮肤基于SparkSkin类,即Skin类的子类。

一般情况下,你应把皮肤类中的所有可视元素放入皮肤类中。这有助于保持模型和视图之间必要的隔离,模型是指逻辑和声明性结构的应用程序;视图是指皮肤的应用程序。皮肤所使用的属性应该定义在组件中(例如:滑动条中拇指滑块的位置),以便他们可由多个皮肤共享。

大部件指定的皮肤使用BasicLayout布局方案。此类型的布局使用约束条件,这意味着你指定的每个元素使用如left、right、top和bottom这些属性来定义和其他元素的距离。你还可以使用绝对定位如x和y坐标来指定每个元素在皮肤类中的位置。

在创建皮肤时你通常不继承现有皮肤类。相反,通常从现有的皮肤类的源码来创建另一个皮肤类更为容易。特别是如果你打算为组件的多个实例或多个组件使用同一个皮肤时,请使用此方法。要更改单个实例的组件的皮肤可以使用MXML图形语法或应用内置样式语法。

在创建Spark的皮肤时,你可以使用MXML、ActionScript、FXG、嵌入式图像或上述任意组合。你在自定义皮肤中最好不要运行时加载资源,例如:图像。

使用皮肤

通常,对某个组件指定Spark皮肤通过CSS或MXML两种方式。使用CSS,通过skinClass样式属性指定皮肤类,如以下示例所示:

s|Button{

skinClass:ClassReference("com.mycompany.skins.MyButtonSkin");

}

当使用MXML指定皮肤时,配置skinClass属性值来指定某个皮肤类名称,如以下示例所示:

<s:ButtonskinClass="com.mycompany.skins.MyButtonSkin"/>

你还可以使用ActionScript语言指定的组件的皮肤。在目标组件上调用setStyle()方法,并指定skinClass样式属性的值,如以下示例所示:

myButton.setStyle("skinClass",Class(MyButtonSkin));

skin类的解析

定义逻辑、图形元素、子组件、状态,和其他对象来组成一个Spark组件的皮肤,自定义Spark皮肤是一个MXML文件。

Spark皮肤类的结构类似其他自定义的MXML组件。他们包含以下元素:
·皮肤根标记或一个皮肤的子类(必须的)
·宿主组件元数据(可选,但推荐使用)
·状态声明(如果定义了宿主组件则必须使用)
·皮肤部件(如果定义了宿主组件则必须使用)
·脚本块(可选)
·图形元素和其他控件(可选)
除了这些的元素,Spark皮肤可以包含MXML语言标记,例如:声明和所需的库等。

根标记(roottags)

皮肤类使用皮肤类或一个皮肤类的子类,例如:SparkSkin,作为他们的根标记。根标记包含皮肤类中所有使用到的命名空间声明。以下通常使用在每个皮肤类文件的顶部:

<s:Skin

xmlns:fx="http://ns.adobe.com/mxml/2009"

xmlns:mx="library://ns.adobe.com/flex/mx"

xmlns:s="library://ns.adobe.com/flex/spark">

你可以在<s:Skin>标记内设置额外的属性,例如:minWidth或scaleX。你也能设置样式属性,例如color和fontWeight。此外,你可以在根标记中指定基于控件状态的值。例如:color.down="0xFFFFFF"。你不能在皮肤类的跟标签中设置includeIn或excludeFrom属性。

如果你为应用程序创建自定义主题,或者如果你在你的自定义皮肤类中不需要支持全局Spark样式,你可以使用skin,而不是SparkSkin作为自定义皮肤的根标记。SparkSkin类对着色样式(例如,chromeColor和symbolColor)添加了支持,支持特定皮肤部件去除着色,支持指定符号的着色。

宿主组件

Spark皮肤类通常对其指定宿主组件。宿主组件是使用皮肤的那个组件。通过指定宿主组件,Spark皮肤可以使用宿主组件的属性,也可以获取该组件实例的引用。下面的示例展示了SparkButton作为宿主组件:

<fx:Metadata>

[HostComponent("spark.components.Button")]

</fx:Metadata>

添加[HostComponent]元数据是可选的,但它可以使Flex执行编译时检查皮肤状态和所需的皮肤部件。没有这种元数据就不能执行编译时检查。

皮肤状态

皮肤状态使皮肤元素关联到组件状态。他们和组件状态不同。例如:当按钮关闭时,按钮的皮肤显示与状态down状态相关联的元素。当按钮弹起时,该按钮将显示up状态与相关联的元素。

自定义皮肤必须声明宿主组件里有的皮肤状态。在运行时,该组件设置合适的状态。皮肤状态使用点符号来指定,即property.state(例如alpha.down定义alpha属性的值处于down状态)。

下面的示例显示了Spark按钮的皮肤状态:
<s:states>

<s:Statename="up"/>

<s:Statename="over"/>

<s:Statename="down"/>

<s:Statename="disabled"/>

</s:states>

皮肤部件

皮肤部件是皮肤类和宿主组件中定义的组件。他们经常提供一种方法使宿主组件能够传送数据给皮肤。该组件也使用皮肤部件来捕获行为事件。

Spark容器皮肤包含一个内容组,它定义了子内容要放入的位置并在此展示。此元素有一个contentGroup的标识。所有有皮肤的容器都有一个contentGroup。内容组是一个静态的皮肤部件。

布局

skin和SparkSkin类使用BasicLayout作为其默认布局方案。这是相当于在皮肤类中这样定义:
<s:layout>

<s:BasicLayout/>

</s:layout>

当有多个图形元素或子组件在皮肤中使用时,布局方案就显得很重要了。BasicLayout依赖于限制和绝对定位来决定组件放置的位置。

子组件

Spark皮肤类通常包括图形元素和构成外观的皮肤的其他组件。

脚本块(可选)

Spark皮肤类可以包括确定皮肤逻辑的一个脚本块。

大多数Spark皮肤在顶部有一个<fx:Script>块。此块通常定义皮肤类的样式属性,包括,皮肤使用的排除样式属性。该标记包括一个特定的属性fb:purpose="styling":
<fx:Scriptfb:purpose="styling">

此属性由Flash生成器使用。当在Flash生成器中创建的该皮肤类副本时,你可以选择该皮肤是否可以有样式。如果有样式,Flash生成器将包括皮肤类这一部分。如果你选择无样式,Flash生成器去除此部分。

语言标签

像任何基于MXML的类,你可以使用根标记内的库标记来声明重复的元素定义。要使用在皮肤类中使用非可视对象,必须包含在声明标记中。

包括的皮肤类版本

虽然新的Sparkskinning体系结构使你创建自己的皮肤更加容易,Flex4还包含几个皮肤集合。

下表描述了Flex4附带的skinning包:

软件包

说明

spark.skins.spark.*

Spark组件的默认皮肤。

spark.skins.wireframe.*

是一个开发应用的简化的主题,它使用"原型"开发。要使用wireframe皮肤,你可以应用wireframe主题,或将该皮肤应用每个组件的基础上。

相关应用主题的信息,请参阅使用主题。

mx.skins.halo.*

MX皮肤对MX组件有效,而和Spark组件皮肤结构并不一致的。通过重写样式,加载helo主题样式,或通过设置compatibility-version为3的编译器选项编译你的应用程序,可以使用helo皮肤而不是Spark皮肤中。

相关信息请看MX组件皮肤。

mx.skins.spark.*

当使用缺省Spark主题时,MX组件使用的缺省皮肤。

这些皮肤在Flex4应用程序中由MX组件使用。这些皮肤在Flex4应用程序中给MX组件类似Spark组件的皮肤。

mx.skins.wireframe.*

MX组件的wireframe皮肤。

皮肤通常遵循这样的命名约定componentNameSkin.mxml。在AdobeFlash平台ActionScript3.0的参考手册中,大多数的皮肤都有几个版本。例如,有四个名为ButtonSkin的类。spark.skins.spark.*包是Spark组件的默认皮肤。

flex4也附带了几个主题,它们使用某些skinning包。更多的信息,请参阅关于主题的文件。

皮肤定义规则

在皮肤类和组件的之间的skinning规则定义了每个成员必须遵守的规则,以便于他们可以彼此进行通信。

皮肤类必须声明的皮肤状态,并定义皮肤部件的外观。皮肤类通常还要指定该宿主组件,并设定在宿主组件中的数据。

组件类必须在元数据中标示皮肤状态和皮肤部件。如果皮肤类要使用宿主组件上的数据,该宿主组件必须定义该数据。

下表显示了skinning规则:

皮肤类

宿主组件

宿主组件

<fx:Metadata>

[HostComponent("spark.components.Button")]

</fx:Metadata>

n/a

皮肤状态

<s:states>

<s:Statename="up"/>

</s:states>

[SkinState("up")];

publicclassButton{

...

}

皮肤部件

<s:Buttonid="upButton"/>

[SkinPart(required="false")]

publicvar:upButtonButton;

数据

text="{hostComponent.title}"

[Bindable]

publicvartitle:String;

编译器验证[HostComponent]、[SkinPart],[SkinState]的元数据(只要[HostComponent]元数据在皮肤类中定义了)。这意味着,皮肤状态和皮肤宿主组件标识的部件必须在皮肤类中声明。

宿主组件中的每个[SkinPart]元数据,编译器都要检查public变量或属性是否存在于皮肤类中。宿主组件中的每个[SkinState]元数据,编译器都要检查皮肤类中是否存在这种状态。有[HostComponent]的元数据的皮肤,编译器尝试解析该宿主组件类,因此它必须完全是可以验证的。

一个组件和其皮肤类之间的规则有效,就可以对该组件使用该皮肤了。

访问宿主组件

Spark皮肤可以指定宿主组件。这不是对组件实例的引用,而是对组件类的引用。使用以下语法定义宿主组件:

<fx:Metadata>

[HostComponent(component_class)]

</fx:Metadata>

例如:

<fx:Metadata>

[HostComponent("spark.components.Button")]

</fx:Metadata>

如果皮肤定义此元数据,Flex会对皮肤类创建该类型的属性--hostComponent。然后,你可以在皮肤内使用此属性来访问宿主组件实例的成员。例如在一个按钮的皮肤,你可以访问按钮的样式属性或其数据(例如:label)。

通过对hostComponent属性进行强类型转换为该组件的引用,你可以访问皮肤的宿主部件的公共属性。
<s:SolidColorcolor="{hostComponent.someColorasuint}"/>

这只适用于直接在宿主组件声明的公共属性。你不能使用此访问宿主组件的私有或受保护属性。

若要访问皮肤内宿主组件的样式属性的值,就无需要指定宿主组件。你可以使用getStyle()方法,如以下示例所示:
<s:SolidColorStrokecolor="{getStyle('color')}"weight="1"/>

你也可以通过使用FlexGlobals.topLevelApplication属性访问根应用程序的属性和方法。更多的信息,请参见访问应用程序属性。

定义皮肤状态

每个有皮肤的组件都有一组可视化的皮肤状态。例如:按下按钮时,按钮的皮肤显示与down状态相关联的元素。按钮弹起时,该按钮将显示与up状态相关联的皮肤元素。

为了使有皮肤的Spark组件和它的皮肤之间的规则有效,你在组件中指定皮肤状态。然后,在皮肤组件的类中定义状态的外表。

皮肤状态在皮肤类中声明,并假设不同的状态都要显示。你可以定义皮肤的状态更改时,皮肤是如何变化的。

子类继承其父的皮肤状态。例如Button类定义皮肤状态up、down、over,和disabled。按钮的子类ToggleButton类除了在按钮中定义的状态还声明了upAndSelected、overAndSelected、downAndSelected状态。

在组件中标识皮肤的状态

宿主部件必须声明它支持的皮肤状态,它只是规则的一部分。若要标识组件类中的皮肤状态,你可以使用[SkinState]元数据标签。此标记的语法如下:

[SkinState("state")]

在类定义前指定元数据。下面的示例定义了四个Button控件的皮肤状态:

[SkinState("up")]

[SkinState("over")]

[SkinState("down")]

[SkinState("disabled")]

publicclassButtonextendsComponent{..}

在皮肤类中定义皮肤状态

Spark皮肤定义规则需要在皮肤类中声明所支持的皮肤状态。你也可以有选择的定义皮肤类的状态的外表。即使在一个皮肤类中声明了皮肤状态,也不需要定义其外表。

再皮肤类中定义一个皮肤状态:
1.在<states>标记中声明皮肤状态。
2.基于组件的状态设置属性的值。此步骤是可选的,但是如果不定义皮肤状态的外表,那么当该组件进入该状态时,皮肤就不会变化。
若要声明在皮肤类中的皮肤状态,使用<s:states>标记作为最外层标签。每个状态对象对应于一个皮肤状态。

下面的示例定义按钮皮肤类支持的四种状态:

<s:Skin...>

<s:states>

<s:Statename="up"/>

<s:Statename="over"/>

<s:Statename="down"/>

<s:Statename="disabled"/>

</s:states>

...

</s:Skin>

你在皮肤类中声明了皮肤状态后,接着你可以定义皮肤状态的外观。要执行此操作,你通过点符号来指定皮肤状态的属性值(property_name.state_name)。over状态中设置一个SolidColorStroke对象的weight属性的值,你指定weight.over属性值如以下示例所示:
<s:SolidColorStrokecolor="0x000000"weight="1"weight.over="2"/>

也可以通过使用includeIn和excludeFrom属性指定的属性状态的值。

最常使用的是指定基于状态的样式属性值。flex基于组件的当前状态使用样式。组件当前状态改变时通知组件,因此皮肤可以实时更新皮肤。

当该组件是处于disabled状态时,通常设置该组件的alpha属性值。这通常是在皮肤类的在外层标记上设置,下面的ButtonSkin类显示了此示例:
<s:Skin

xmlns:fx="http://ns.adobe.com/mxml/2009"

xmlns:s="library://ns.adobe.com/flex/spark"

minWidth="21"minHeight="21"

alpha.disabled="0.5">

另一个例子是根据其他状态,按钮标签的alpha属性更改。皮肤设置labelDisplay的alpha属性的值。当按钮在up状态时,标签alpha为1。按钮在over状态时,标签有alpha值为0.25,如以下示例所示:
<?xmlversion="1.0"encoding="utf-8"?>

<!--SparkSkinning/StatesButtonExample.mxml-->

<s:Application

xmlns:fx="http://ns.adobe.com/mxml/2009"

xmlns:mx="library://ns.adobe.com/flex/mx"

xmlns:s="library://ns.adobe.com/flex/spark">


<s:Buttonlabel="AlphaChanges"skinClass="mySkins.MyAlphaButtonSkin"/>


</s:Application>

TheexecutingSWFfileforthepreviousexampleisshownbelow:
对于此示例的皮肤类,如下所示:
<?xmlversion="1.0"encoding="utf-8"?>

<!--SparkSkinning/mySkins/MyAlphaButtonSkin.mxml-->

<s:Skin

xmlns:fx="http://ns.adobe.com/mxml/2009"

xmlns:mx="library://ns.adobe.com/flex/mx"

xmlns:s="library://ns.adobe.com/flex/spark"

minWidth="21"minHeight="21">


<fx:Metadata>

[HostComponent("spark.components.Button")]

</fx:Metadata>


<!--SpecifyonestateforeachSkinStatemetadatainthehostcomponent'sclass-->

<s:states>

<s:Statename="up"/>

<s:Statename="over"/>

<s:Statename="down"/>

<s:Statename="disabled"/>

</s:states>


<s:Rectleft="0"right="0"top="0"bottom="0"width="69"height="20"radiusX="2"radiusY="2">

<s:stroke>

<s:SolidColorStrokecolor="0x000000"weight="1"/>

</s:stroke>

</s:Rect>


<s:Labelid="labelDisplay"

alpha.up="1"

alpha.down=".1"

alpha.over=".25"

horizontalCenter="0"verticalCenter="1"

left="10"right="10"top="2"bottom="2">

</s:Label>

</s:Skin>


基于状态的组件上,你可以设置任何属性。不仅限于样式属性。例如,你可以基于它的状态更改Button控件的标签,如以下示例所示:
<?xmlversion="1.0"encoding="utf-8"?>

<!--SparkSkinning/ChangeLabelBasedOnStateExample.mxml-->

<s:Application

xmlns:fx="http://ns.adobe.com/mxml/2009"

xmlns:mx="library://ns.adobe.com/flex/mx"

xmlns:s="library://ns.adobe.com/flex/spark">


<s:Buttonid="myButton"label="BasicButton"skinClass="mySkins.ChangeLabelBasedOnState"/>


</s:Application>

TheexecutingSWFfileforthepreviousexampleisshownbelow:
自定义的皮肤类如下所示:
<?xmlversion="1.0"encoding="utf-8"?>

<!--SparkSkinning/mySkins/ChangeLabelBasedOnState.mxml-->

<s:Skin

xmlns:fx="http://ns.adobe.com/mxml/2009"

xmlns:mx="library://ns.adobe.com/flex/mx"

xmlns:s="library://ns.adobe.com/flex/spark"

minWidth="21"minHeight="21">


<fx:Metadata>

[HostComponent("spark.components.Button")]

</fx:Metadata>


<!--SpecifyonestateforeachSkinStatemetadatainthehostcomponent'sclass-->

<s:states>

<s:Statename="up"/>

<s:Statename="over"/>

<s:Statename="down"/>

<s:Statename="disabled"/>

</s:states>


<s:Rectleft="0"right="0"top="0"bottom="0"width="69"height="20"radiusX="2"radiusY="2">

<s:stroke>

<s:SolidColorStrokecolor="0x000000"weight="1"/>

</s:stroke>

<!--Addthisfilltomakethe"hitarea"covertheentirebutton.-->

<s:fill>

<s:SolidColorcolor="0xFFFFFF"/>

</s:fill>

</s:Rect>


<s:Labelid="labelDisplay"

text.up="UP"text.over="OVER"text.down="DOWN"

horizontalCenter="0"verticalCenter="1"

left="10"right="10"top="2"bottom="2">

</s:Label>

</s:Skin>

如果确定了的组件上的皮肤状态,但是没有在皮肤类内中声明它,Flex会引发一个编译器错误,如果设置[HostComponent]元数据。你不需要在皮肤类中设定皮肤状态的外观,但你需要在这种情况下在皮肤类中声明它。

如果你在皮肤类中设置某个状态的样式属性的值时,而该状态没有在宿主组件中标识它,Flex会引发一个编译器错误。此错误检查有助于强制遵守该组件与皮肤之间的规范。

除了根据条件设置属性值,可以还使用包括或排除方法来将某个图形元素归属某个状态。如果要这样做,你可以使用includeIn和excludeFrom属性来定义其状态图形元素的归属。

下面的示例显示了在Button控件处于down状态时,显示一个透明的灰色框:
<?xmlversion="1.0"encoding="utf-8"?>

<!--SparkSkinning/IncludeButtonExample.mxml-->

<s:Application

xmlns:fx="http://ns.adobe.com/mxml/2009"

xmlns:mx="library://ns.adobe.com/flex/mx"

xmlns:s="library://ns.adobe.com/flex/spark">


<s:Buttonlabel="ClickMeIntheButtonClass"skinClass="mySkins.MyIncludeButtonSkin"color="0xCCC333"/>


</s:Application>

TheexecutingSWFfileforthepreviousexampleisshownbelow:
自定义的皮肤类如下所示:
<?xmlversion="1.0"encoding="utf-8"?>

<!--SparkSkinning/mySkins/MyIncludeButtonSkin.mxml-->

<s:Skin

xmlns:fx="http://ns.adobe.com/mxml/2009"

xmlns:mx="library://ns.adobe.com/flex/mx"

xmlns:s="library://ns.adobe.com/flex/spark"

minWidth="21"minHeight="21">


<fx:Metadata>

[HostComponent("spark.components.Button")]

</fx:Metadata>


<!--SpecifyonestateforeachSkinStatemetadatainthehostcomponent'sclass-->

<s:states>

<s:Statename="up"/>

<s:Statename="over"/>

<s:Statename="down"/>

<s:Statename="disabled"/>

</s:states>


<s:Rectleft="0"right="0"top="0"bottom="0"width="69"height="20"radiusX="2"radiusY="2">

<s:stroke>

<s:SolidColorStrokecolor="0x000000"weight="1"/>

</s:stroke>

</s:Rect>


<s:Labelid="labelDisplay"

horizontalCenter="0"verticalCenter="1"

left="10"right="10"top="2"bottom="2">

</s:Label>


<!--Highlight(downstateonly)-->

<!--NotethatyoumightneedtoadjusttheradiusXandradiusYproperties.-->

<s:Rectleft="0"right="0"top="0"bottom="0"width="69"height="20"includeIn="down">

<s:fill>

<s:SolidColorcolor="0x000000"alpha="0.25"/>

</s:fill>

</s:Rect>

</s:Skin>

当你使用excludeFrom属性将某个图形元素排除在某个状态时,Flex从其父级的子列表中删除它。该元素将不再被引用。

如果图形元素不在皮肤类中指定includeIn或excludeFrom属性,图形元素是默认情况下在所有控件的状态使用。

你可以指定多个要包括或排除的状态,它们之间使用逗号分隔。下面的示例将矩形图形元素排除在宿主组件的over、down状态之外:

<s:Rectleft="0"right="0"top="0"bottom="0"width="69"height="20"excludeFrom="over,down">

只可以在MXML中设置excludeFrom和includeIn属性。不能在ActionScript中设置这些属性的值。

当使用皮肤类后,只要它们的父类是可视的,所有类都支持在皮肤类中使用includeIn和excludeFrom属性。这意味着不能对该皮肤文件的根标记中设置这些属性,也不能在分级属性中设置它们。例如,下面显示一个有效和无效的includeIn属性的使用:
<s:states>

<s:Statename="StateA"/>

</s:states>


<!—这是一个有效的includeIn属性的使用:-->

<s:Button>

<s:label.StateA>

<fx:String>MyLabel</fx:String>

</s:label.StateA>

</s:Button>


<!--这是一个无效的includeIn属性的使用,String的父类不是一个可视的对象:-->

<s:Button>

<s:label>

<fx:StringincludeIn="StateA">MyLabel</fx:String>

</s:label>

</s:Button>

如果你从一个皮肤中排除某些图形元素,组件有时自己调整大小,或者根据状态循环更改它的外观。例如:如果你对按钮皮肤的labelDisplay的excludeFrom属性的值设置为down,该标签在用户单击按钮时将消失。这样一来,按钮在down状态时将自行调整大小。下面的示例显示了这种现象:
<?xmlversion="1.0"encoding="utf-8"?>

<!--SparkSkinning/HideLabelOnDownExample.mxml-->

<s:Application

xmlns:fx="http://ns.adobe.com/mxml/2009"

xmlns:mx="library://ns.adobe.com/flex/mx"

xmlns:s="library://ns.adobe.com/flex/spark">


<s:Buttonid="myButton"

skinClass="mySkins.HideLabelOnDownSkin"

label="ThisIsALongButtonLabel"/>


</s:Application>

TheexecutingSWFfileforthepreviousexampleisshownbelow:
自定义皮肤类如下所示:
<?xmlversion="1.0"encoding="utf-8"?>

<!--SparkSkinning/mySkins/HideLabelOnDownSkin.mxml-->

<s:Skin

xmlns:fx="http://ns.adobe.com/mxml/2009"

xmlns:mx="library://ns.adobe.com/flex/mx"

xmlns:s="library://ns.adobe.com/flex/spark"

minWidth="21"minHeight="21">


<fx:Metadata>

[HostComponent("spark.components.Button")]

</fx:Metadata>


<!--SpecifyonestateforeachSkinStatemetadatainthehostcomponent'sclass-->

<s:states>

<s:Statename="up"/>

<s:Statename="over"/>

<s:Statename="down"/>

<s:Statename="disabled"/>

</s:states>


<s:Rect

left="0"right="0"

top="0"bottom="0"

width="69"height="20"

radiusX="2"radiusY="2">

<s:stroke>

<s:SolidColorStrokecolor="0x000000"weight="1"/>

</s:stroke>

</s:Rect>


<s:Labelid="labelDisplay"

excludeFrom="down"

horizontalCenter="0"verticalCenter="1"

left="10"right="10"top="2"bottom="2">

</s:Label>

</s:Skin>

按钮的大小根据标签的内容动态调整。排除标签导致标签本身从父类中删除。

为了阻止按钮自动调整大小,可以设置alpha.down的属性值为0或visible.down的属性值为false,而不是将整个组件排除在down状态之外,这样标签文本不会消失,按钮也不会自动调整自己,因为标签文本并没有从父类中删除掉,请看下面的示例:
<?xmlversion="1.0"encoding="utf-8"?>

<!--SparkSkinning/HideLabelOnDownExample2.mxml-->

<s:Application

xmlns:fx="http://ns.adobe.com/mxml/2009"

xmlns:mx="library://ns.adobe.com/flex/mx"

xmlns:s="library://ns.adobe.com/flex/spark">


<s:Buttonid="myButton"

skinClass="mySkins.HideLabelOnDownSkin2"

label="ThisIsALongButtonLabel"/>


</s:Application>

TheexecutingSWFfileforthepreviousexampleisshownbelow:
自定义皮肤类如下所示:
<?xmlversion="1.0"encoding="utf-8"?>

<!--SparkSkinning/mySkins/HideLabelOnDownSkin2.mxml-->

<s:Skin

xmlns:fx="http://ns.adobe.com/mxml/2009"

xmlns:mx="library://ns.adobe.com/flex/mx"

xmlns:s="library://ns.adobe.com/flex/spark"

minWidth="21"minHeight="21">


<fx:Metadata>

[HostComponent("spark.components.Button")]

</fx:Metadata>


<!--SpecifyonestateforeachSkinStatemetadatainthehostcomponent'sclass-->

<s:states>

<s:Statename="up"/>

<s:Statename="over"/>

<s:Statename="down"/>

<s:Statename="disabled"/>

</s:states>


<s:Rect

left="0"right="0"

top="0"bottom="0"

width="69"height="20"

radiusX="2"radiusY="2">

<s:stroke>

<s:SolidColorStrokecolor="0x000000"weight="1"/>

</s:stroke>

</s:Rect>


<s:Labelid="labelDisplay"

visible.down="false"

horizontalCenter="0"verticalCenter="1"

left="10"right="10"top="2"bottom="2">

</s:Label>

</s:Skin>

皮肤部件(skinparts)

某些组件有多个皮肤部件。例如:NumericStepper包含一个up按钮,一个down的按钮和text。这些部件由该组件的声明。皮肤定义其外观。组件中定义的部件在皮肤中可以是可选的也可以是必需的。

皮肤部件是皮肤规范的重要组成部份。他们让组件的实例与皮肤进行交互并且可以将数据压入皮肤文件来定义它的行为。

皮肤部件在Spark皮肤类中不必是最顶层的标签。他们可以在MXML文件中的任何位置。

若要在组件中声明一个皮肤部件,你可以使用[SkinPart]元数据。例如Button类在ButtonBase类中定义皮肤部件:

[SkinPart(required="false")]

publicvarlabelDisplay:TextBase;

ButtonSkin类定义了一个标签作为labelDisplay部件:

<s:Labelid="labelDisplay"

textAlign="center"

verticalAlign="middle"

maxDisplayedLines="1"

horizontalCenter="0"verticalCenter="1"

left="10"right="10"top="2"bottom="2">

</s:Label>

在此的示例中,labelDisplay皮肤部件从技术上说不是必需的(required="false"),但没有它,Flex不能在button控件上绘制一个标签。required的属性的默认值为false。Button类和皮之间的规范规定了当你设置按钮上标签的属性,该值被传递到皮肤文件,如果labelDisplay皮肤部件存在,就修改labelDisplay皮肤部件的文本值。

部件由其id属性标识。在皮肤类中部件的id属性必须与皮肤部件宿主组件中的属性名称相匹配。这将有助于强制遵守皮肤与宿主组件之间的规范。例如:你在组件中使用下面的声明:

[SkinPart(required="true")]

publicvartextInput:TextInput;

皮肤类将TextInput实例的id属性设置为textInput,如下示例所示:

<s:TextInputid="textInput".../>

主要有两种类型的皮肤部件:静态和动态。静态部件被皮肤自动实例化。可能只有一个静态部件的实例。例如,VScrollBar类具有四个静态部件:track、thumb、incrementButton和descrementButton。Button类有一个静态部件:label。

动态部件在需要时被实例化。动态的部件可以有多个实例。动态部件定义在皮肤的声明块中,以便可以被使用的皮肤实例化一个或多个实例。例如,滑块类的DataTip是一个动态的皮肤部件。在VSliderSkin和HSliderSkin,dataTip皮肤部件在声明块中定义。

在你的宿主组件中,可以将动态皮肤部件类型定义为一个IFactory。例如,滑块类的dataTip定义为:
[SkinPart(required="false",type="mx.core.IDataRenderer")]

publicvardataTip:IFactory;

在运行时加载组件皮肤过程中,SkinnableComponent基类会找到皮肤的所有部件,分配已找到的部件,如果所需的部件在皮肤内没有定义,则会引发运行时错误。找到被延迟的部件(因为它们在皮肤中被定义其属性值),因为当组件首次被实例化时,它们是空值。

在组件中使用皮肤类

在定义了一个皮肤后,你可以通过以下方式将它应用到一个组件:
·CSS
·MXML
·ActionScript
可以通过CSS将一个皮肤与一个组件联系起来,在样式表中设置skinClass属性的值。你可以使用类型或类选择器将皮肤类应用到一个组件中。

下面的示例通过使用一个类型选择器将mySkins.NewPanelSkin类使用到所有的Panel容器中:

@namespaces"library://ns.adobe.com/flex/spark";

s|Panel{

skinClass:ClassReference("mySkins.NewPanelSkin");

}

下面的示例使用myButtonStyle类选择器将mySkins.CustomButtonSkin类关联到所有组件中:

.myButtonStyle{

skinClass:ClassReference("mySkins.CustomButtonSkin");

}

...

<s:Buttonlabel="SparkButton"className="myButtonStyle"/>

若要在MXML文件中将皮肤和组件关联到一起,你可以通过行内设定的方法设置skinClass属性值。下面是Panel容器配置mySkins.NewPanelSkin皮肤的示例:

<s:PanelskinClass="mySkins.NewPanelSkin"/>

使用CSS配置皮肤的优点是你可以根据类型或类选择器将某个皮肤应用到所有的特定类型的组件上(例如,所有的按钮)或所有特定的类上(例如,样式名称为"myButtonStyle"的所有组件)。

CSS支持继承。如果使用类型选择器将一个Button控件按钮中使用了某个皮肤,该皮肤将所有Button控件和Button控件的子类(例如:ToggleButton类)都使用该皮肤。这可能并不是你想要的结果。如果你将所有Label控件使用某个新皮肤,具有Label标签子组件的组件也将使用该皮肤。这样一来,你应使用类选择器只将皮肤应用于基本组件。

在MXML中设置一个皮肤类只允许你对组件的实例使用皮肤。

你也可以在ActionScript中对组件使用皮肤类。在的组件上调用setStyle()方法,并设置skinClass样式属性的值。在setStyle()方法中,你必须将皮肤转换类。

下面的示例为按钮使用了自定义皮肤类:
<?xmlversion="1.0"encoding="utf-8"?>

<!--SparkSkinning/SimpleLoadExample.mxml-->

<s:Application

xmlns:fx="http://ns.adobe.com/mxml/2009"

xmlns:mx="library://ns.adobe.com/flex/mx"

xmlns:s="library://ns.adobe.com/flex/spark">


<fx:Script>

importmySkins.*;


privatefunctionchangeSkinClickHandler():void{

myButton.setStyle("skinClass",Class(MyButtonSkin));

}

</fx:Script>


<s:Buttonid="myButton"

label="ClickMe"

color="0xFFFFF"

click="changeSkinClickHandler()"/>


</s:Application>

TheexecutingSWFfileforthepreviousexampleisshownbelow:
自定义皮肤类如下所示:
<?xmlversion="1.0"encoding="utf-8"?>

<!--SparkSkinning/mySkins/MyButtonSkin.mxml-->

<s:Skin

xmlns:fx="http://ns.adobe.com/mxml/2009"

xmlns:mx="library://ns.adobe.com/flex/mx"

xmlns:s="library://ns.adobe.com/flex/spark"

minWidth="21"minHeight="21">


<fx:Metadata>

[HostComponent("spark.components.Button")]

</fx:Metadata>


<!--SpecifyonestateforeachSkinStatemetadatainthehostcomponent'sclass-->

<s:states>

<s:Statename="up"/>

<s:Statename="over"/>

<s:Statename="down"/>

<s:Statename="disabled"/>

</s:states>


<s:Rectleft="0"right="0"top="0"bottom="0"width="69"height="20"radiusX="2"radiusY="2">

<s:stroke>

<s:SolidColorStrokecolor="0x000000"weight="1"/>

</s:stroke>

</s:Rect>


<s:Labelid="labelDisplay"

horizontalCenter="0"verticalCenter="1"

left="10"right="10"top="2"bottom="2">

</s:Label>

</s:Skin>

在应用程序中使用皮肤类之前,确保已经导入了相应的皮肤类的包。

就像在CSS使用皮肤类一样,你可以在ActionScript中队特定组件类型使用皮肤。在组件的样式声明中调用setStyle()方法。下面的例子展示了对应用程序中的所有按钮使用自定义皮肤:
<?xmlversion="1.0"encoding="utf-8"?>

<!--SparkSkinning/ASTypeSelectorLoadExample.mxml-->

<s:Application

xmlns:fx="http://ns.adobe.com/mxml/2009"

xmlns:mx="library://ns.adobe.com/flex/mx"

xmlns:s="library://ns.adobe.com/flex/spark">


<s:layout>

<s:VerticalLayout/>

</s:layout>


<fx:Script>

importmySkins.*;


privatefunctionchangeSkinClickHandler():void{

styleManager.getStyleDeclaration("spark.components.Button").setStyle("skinClass",Class(MyButtonSkin));

}

</fx:Script>


<s:Buttonid="myButton1"label="ClickMe"color="0xFFFFF"

click="changeSkinClickHandler()"/>

<s:Buttonid="myButton2"label="ClickMe"color="0xFFFFF"

click="changeSkinClickHandler()"/>

<s:Buttonid="myButton3"label="ClickMe"color="0xFFFFF"

click="changeSkinClickHandler()"/>


</s:Application>

TheexecutingSWFfileforthepreviousexampleisshownbelow:

皮肤状态和皮肤部件的文档化

ASDoc工具支持在[SkinState]和[SkinPart]的元数据标记之前进行文档描述。

你可以在[SkinState]元数据标签上方通过添加注释的方法进行文档描述,如以下示例所示:

/**

*Upstateofthebutton.

*/

[SkinState("up")]

若要队[SkinPart]元数据描述,ASDoc工具使用来自组件类文件中的变量描述。你不用在实际的元数据标记上添加的注释,如以下示例所示:

[SkinPart(required="false")]

/**

*Askinpartthatdefinesthelabelofthebutton.

*/

publicvarlabelDisplay:TextGraphicElement;

ASDoc工具将皮肤状态文档添加到类的“皮肤状态”段。它将皮肤部件文档添加到类的"皮肤部件"部件的文档段中。

有关ASDoc实用程序的详细信息,请参阅ASDoc。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: