首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 媒体动画 > flex >

[译] Flex 四 皮肤功能介绍 -续

2012-10-27 
[译] Flex 4 皮肤功能介绍 -续英文原文:?http://www.adobe.com/devnet/flex/articles/flex4_skinning.html

[译] Flex 4 皮肤功能介绍 -续

英文原文:?http://www.adobe.com/devnet/flex/articles/flex4_skinning.html

本文翻译原创链接: http://www.smithfox.com/?e=34 转载请注明

翻译:?smithfox

?

?

上接:

http://smithfox.iteye.com/admin/blogs/847465

?

制作slider皮肤

皮肤parts不仅可以推送组件数据到皮肤中,组件也可以用它们来注册行为。为了讲得更明白,以slider组件为例。slider两个主要parts是轨迹条和滑动块。在这个例子中,该组件没有把任何数据推送到皮肤来显示,但它添加了事件监听器到parts中并且会根据组件的value属性执行滑动块的布局。例如,当点击轨迹条,组件会更新其value属性并且定位滑动块到适当位置。此外,还有动态皮肤parts,数据提示,这是用来拖动滑块时显示弹出的提示信息。 在图6所示是一个简单slider和一个修改后的slider。

[译] Flex 四 皮肤功能介绍 -续

图6: 修改后的slider(左边) 和原来的slider (右边)

为构建这个, 你的皮肤文件必须声明三个皮肤parts: thumb(滑块), track(轨迹条), and dataTip(数据提示)。
MySliderSkin.mxml

图7: NoteCard 组件例子

主应用程序仅创建一个有点旋转的语录NoteCard。 有趣的部分是NoteCard类,它扩展了spark.components.supportClasses.SkinnableComponent类并且在生命周期方法中添加代码。
NoteCard.as:

01package02{03??04[SkinState("normal")]05[SkinState("disabled")]06public class NoteCard extends SkinnableComponent07{08????public function NoteCard()09????{10????????super();11????}12?????13????[SkinPart(required="true")]14????public var labelDisplay:TextBase;15?????16????[SkinPart(required="false")]17????public var closeButton:Button;18?????19????private var _text:String;20??21????public function get text():String22????{23????????return _text;24????}25??26????public function set text(value:String):void27????{28????????if (_text == value)29???????????return;30????????_text = value;31????}32??33????...34}35}

此组件声明数据属性,皮肤states,皮肤parts。 对于数据,NoteCard有一个公共的text属性。 此外,NoteCard有两个皮肤states,normal和disabled,用SkinStates元数据声明在类声明代码的上面。 这就告诉皮肤,它需要实现这两个states。
NoteCard还有两个皮肤parts,是通过SkinPart元数据声明的。 SkinPart元数就直接声明在皮肤part名称之上。 当前例子,labelDisplay是必需的TextBase类皮肤part,closeButton是一个可选的Button类皮肤part。
由于皮肤是运行时载入,当组件第一次启动时,你不能保证有一定有皮肤。 你也不能保证已经有了全部的皮肤parts,尤其是他们是可选的。 框架负责了这些事情: 衔接part声明和组件属性定义,并且通过皮肤生命周期方法通知组件parts已经准备好了。?


实现皮肤states

为实现皮肤states,你需重写getCurrentSkinState()方法以返回皮肤当前所处状态,当前例子中,它会返回"normal"或"disabled"。当一些事件导致皮肤state变得无效时,组件应该调用invalidateSkinState()方法。NoteCard.as

01package02{03[SkinState("normal")]04[SkinState("disabled")]05public class NoteCard extends SkinnableComponent06{07????...?? 08????override public function set enabled(value:Boolean) : void09????{10????????if (enabled != value)11???????????invalidateSkinState();12????????super.enabled = value;13????}14?????15????override protected function getCurrentSkinState() : String16????{17????????if (!enabled)18???????????return "disabled";19????????return "normal"20????}21?????22????...23}24}

当设置enabled属性时,enabled setter调用invalidateSkinState()以通知皮肤,组件的state需要改变,这样getCurrentSkinState()随即会被调用。


处理皮肤parts

处理皮肤parts,有两种主要方法应该要重写,partAdded()和partRemoved()。这些方法会告诉你一个特定的皮肤part被添加了或被删除了。当装载一个皮肤时Parts将被加入或是删除。皮肤是在运行时交换的,并且延迟加载的,所以只有在某种states情况下或者是一个动态part刚刚被创建时part才会被加入。在partAdded()方法你可以设置你想要的任何数据到part,而且也可以attach一些事件侦听到part上。当part被删除时,你应该在partRemoved()方法中做相反的事情。
NoteCard.as

01package02{03public class NoteCard extends SkinnableComponent04{05????[SkinPart(required="true")]06????public var labelDisplay:TextBase;07?????08????[SkinPart(required="false")]09????public var closeButton:Button;10?????11????public function set text(value:String):void12????{13????????if (_text == value)14???????????return;15????????_text = value;16?????????17????????if (labelDisplay)18???????????labelDisplay.text = value;19????}20??21????override protected function partAdded(partName:String, instance:Object) : void22????{23???????super.partAdded(partName, instance);24????????25???????if (instance == labelDisplay)26???????????labelDisplay.text = _text;27???????if (instance == closeButton)28???????????closeButton.addEventListener(MouseEvent.CLICK, closeButton_clickHandler);29????}30?????31????override protected function partRemoved(partName:String, instance:Object) : void32????{33???????super.partRemoved(partName, instance);34?????????35????????if (instance == closeButton)36???????????closeButton.removeEventListener(MouseEvent.CLICK, closeButton_clickHandler);37????}38?????39????protected function closeButton_clickHandler(event:MouseEvent) : void40????{41???????event.stopPropagation();42????????43???????IVisualElementContainer(parent).removeElement(this);44????}45?}46}

在partAdded()方法中,当labelDisplay part加入时,我设置text到这个part。此外,在text属性的setter方法中,我检查,看看是否已经加入labelDisplay,如果是的话,我重新设置labelDisplay.text为组件的_text值以保证和组件text属性同步。在partAdded()方法中,我添加一个click事件监听器到closeButton皮肤part。在partRemoved()我一定要删除这个click事件监听器。
作为一个SkinnableComponent ,你需要做的就是利用这个强大的换肤机制。 当有人创造了某个组件的皮肤,他们必须实现皮肤states和皮肤parts以得到期望的组件行为。 在图6所示的皮肤在样例源代码中可以找到,即使这是一个简单的组件定义,你依然可以用不同的皮肤完全改变它的外观和体验。这就是皮肤真正的力量。
注:当创建可变换皮肤组件,您可能要决定某些行为是属于皮肤的还是组件。 没有一个明确的硬性的规则。只要能让你的工作更容易就行了。 作为一般指导,一切外观和感观的定义应在皮肤MXML文件中声明。 另一方面,如果有多个皮肤想要某个特殊行为,那么将这个行为放在组件可能是一个好主意。例如,slider中滑块的定位是做在VSlider和HSlider,没有在皮肤上。


下一步到哪里

Flex 4皮肤发生了重大修改。 明确分开了组件和皮肤。该组件包含了数据,行为和核心逻辑,而皮肤定义了组件的外观和体验。组件由ActionScript编写而皮肤写在MXML中,这是托FXG和新states语法的福。 组件和皮肤通过皮肤契约进行交互。 又因为它们是各自独立的文件,所以新的皮肤很容易应用到组件上从而完全改变他们的外观。
欲了解更多的Flex 4皮肤信息,请查看 皮肤架构规范 以及 Gumbo组件架构白皮书。

热点排行