FLEX皮肤实例4_skinpart

转载 2013年12月05日 10:59:32
1.概述
      上篇文章《FLEX皮肤实例3_自定义类与皮肤交互数据》,相关资料《FLEX皮肤2_皮肤原理》。

      皮肤与组件的数据交互是双向中的
     1.皮肤调用组件属性:使用:
          [HostComponent("spark.components.Button")]
          例:{hostComponent.label}

     2.组件调用皮肤中的组件
          [SkinPart(required="true")]
          public var button:Button;
          这就是所谓的skin part

      Skin part也是skin contract的重要组成部分。

      
      Spark框架中许多组件已经内置了skin parts。
      比如,在官方《flex 4 API》中,Button组件只有一个名为labelDisplay的skin part(它继承自ButtonBase类)是TextBase类的实例,用来显示按钮标签。
      详见http://www.fising.cn/docs/AS3_Reference/spark/components/Button.html#SkinPartSummary。

      比如:Panel类内置了3个skin part. contentGroup存储并布局所有子组件。controlBarGroup处理一个可选的控制条布局。titleDisplay用来显示用户传递过 来的面板title标题属性。这些skin part都是静态的;每个实例都只有一个。
      详见:http://www.fising.cn/docs/AS3_Reference/spark/components/Panel.html

      通过Part不仅可以推送组件数据到皮肤中,组件也可以用它们来注册行为。定义了这些Part之后,由组件负责功能逻辑的实现,而皮肤则只负责所有可视化的内容及布局。如icon的外观表现通过Skin表示,而icon的事件监听则由组件负责。

  1. //组件 
  2. [SkinPart(required="true")] 
  3. public var icon:Image; 
  4. //皮肤 
  5. <mx:Image id="icon"/>
      SkinnableComponent还提供了partAdded和partRemoved方法,在增加或删除SkinPart时会调用这些方法。
      当part加载的时候,partAdded()会被调用,当part移除的时候partRemoved()方法会被调用。因此我们可以在这两个方法中添加相关事件处理逻辑。

2. skin part类型
skin part分为static、dynamic、deferred(延迟)。
  .static
      skin part随着皮肤实例化。它们在整个皮肤周期永远是可访问的,并且任何静态part实例只有一个。
      比如Button组件中的labelDisplay皮肤part就是静态的,所以你不能创建另一个名为labelDisplay的skin part,但你可以访问labelDisplay.

  .dynamic
      动态的skin parts是在需要时被实例化,许多组件不需要。
      这些通常是特定组件有关皮肤不可或缺的工作。
      例如,Spark ButtonBar组件有三个动态皮肤部件:firstButton, lastButton, 和middleButton。这些动态的skin parts负责处理按钮条上每个按钮的皮肤,但由于每个特定按钮可能有不同的样式,这取决于ButtonBar实例中需要应用动态实例化皮肤的条件。例如,一个只有两个按钮的ButtonBar并不需要middleButton因为它只会有左右按钮。

      动态的skin parts用于在运行时需要实例化子元素的那些组件。它们是mx.core.IFactory的实例,这个接口类被用来创建其它组件实例,因为该皮肤在应用程序运行时将创建这些所需新部件。

  .deferred
     延迟skin parts根据一些触发器的排序来实例化。当皮肤被创建和应用到组件上时这些部件可能不存在,直到用户或系统与该组件交互时它们才被添加。

Adobe官方给出的skin parts生命周期。


      程序运行中skin发生变化,就会调用detachSkin()方法,所有skin part相关的partRemoved()方法也会自动调用,开发人员可以在这两个方法里添加相应的事件监听。

  有些复杂的component 可能需要在skin创建后某个不确定的时间与skin part进行交互。Component需要知道partAdded()方法可能在skin初始化很久以后才会被调用。这样的skin part被称为延迟的(deferred part)。一个典型的例子就是TabNavigator, 当用户点击了某个Tab之后,component才会知道新的part然后调用partAdded()方法。

3. 数据传递时绑定hostComponent VS 皮肤parts
组件数据与皮肤的传递可通过二种方式,代码可参见Button
1.通过hostComponent,将组件属性与皮肤中的元素进行绑定
代码参见http://www.smithfox.com/?e=34
ButtonSkin3.mxml:

点击(此处)折叠或打开

  1. <s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009" 
  2. xmlns:s="library://ns.adobe.com/flex/spark" alpha.disabled=".5">
  3.  
  4.     <fx:Metadata>
  5.        [HostComponent("spark.components.Button")]
  6.     </fx:Metadata>
  7.  
  8.     ...
  9.     
  10.     <!-- text -->
  11.     <s:Label text="{hostComponent.label}" color="0x131313" 
  12.             textAlign="center"
  13.             verticalAlign="middle"
  14.             horizontalCenter="0" verticalCenter="1"
  15.             left="12" right="12" top="6" bottom="6"
  16.      /> 
  17. </s:Skin>

2.skin part
    在皮肤内定义一个id,并且在组件内定义一个skin part,按钮会识别这个skin part,从面将label属性推送到皮肤中。
代码参见http://www.smithfox.com/?e=34
ButtonSkin4.mxml:

点击(此处)折叠或打开

  1. <!-- text -->
  2.     <s:Label id="labelDisplay" color="0x131313" textAlign="center"
  3.             verticalAlign="middle"
  4.             horizontalCenter="0" verticalCenter="1"
  5.             left="12" right="12" top="6" bottom="6"
  6.     />
ButtonBase.as

  1. [SkinPart(required="false")]
  2. public var labelDisplay:IDisplayText;
    Label不再绑定到hostComponent。相反,我给它一个id labelDisplay ,这是一个按钮组件所需的皮肤part。按钮组件自动处理数据,将它的label属性推送到labelDisplay。
    但是这里需要注意的事,我们不能直接直接给Button中的labelDisplay属性赋值。

4. Button按钮代码导读
1.spark.components.supportClasses.ButtonBase定义了SkinState元数据: up, over, down disabled。

2.spark.components.supportClass.ButtonBase类定义了SkinPart的成员变量labelDisplay,

  1. [SkinPart(required="false")]
  2. public var labelDisplay:TextBase;
      这就表示Button的皮肤中可以定义有文本对象,id为labelDisplay.
      required="false",表示这个part是可选的,如果为true,则表示皮肤中必须有一个TextBase对象。

3.对Button赋值
     现在对Button的label属性进行赋值,其执行过程如下:
(1) 调用set label函数
    public function set label(value:String):void
    {
        // ButtonBase中并没有label属性,而是将值传递给了content
        content = value;
    }

(2) 调用set content函数

点击(此处)折叠或打开

  1.     [Bindable("contentChange")]
  2.     public function get content():Object
  3.     {
  4.         return _content;
  5.     }
  6.     public function set content(value:Object):void
  7.     {
  8.         _content = value;
  9.         // 这里才将传递的label值传递给labelDisplay skin part
  10.         if (labelDisplay)
  11.             labelDisplay.text = label;
  12.         // 派发事件,通知与content绑定的对象,content的值被修改了
  13.         dispatchEvent(new Event("contentChange"));
  14.     }

      labelDisplay是静态的,在声明周期中只会存在唯一的实例。当加载静态SkinPart的皮肤时,SkinnableComponent基类负责将所有的静态part从skin加载到component中。加载完毕之后,component就可以直接使用这些实例了。
      SkinnableComponent还提供了partAdded和partRemoved方法,在增加或删除SkinPart时会调用这些方法。
      当part加载的时候,partAdded()会被调用,当part移除的时候partRemoved()方法会被调用。因此我们可以在这两个方法中添加相关事件处理逻辑。

点击(此处)折叠或打开

  1. override protected function partAdded(partName:String, instance:Object):void
  2.     {
  3.         super.partAdded(partName, instance);
  4.         
  5.         if (instance == labelDisplay)
  6.         {
  7.             labelDisplay.addEventListener("isTruncatedChanged",labelDisplay_isTruncatedChangedHandler);
  8.             
  9.             // 当添加文本框时,如果_content有值,则将这个值赋给文本框
  10.             if (_content !== undefined)
  11.                 labelDisplay.text = label;
  12.         }
  13.         else if (instance == iconDisplay)
  14.         {
  15.             iconDisplay.source = getStyle("icon");
  16.         }
  17.     }
  18.     
  19.     override protected function partRemoved(partName:String, instance:Object):void
  20.     {
  21.         super.partRemoved(partName, instance);
  22.         
  23.         if (instance == labelDisplay)
  24.         {
  25.             labelDisplay.removeEventListener("isTruncatedChanged",
  26.                                              labelDisplay_isTruncatedChangedHandler);
  27.         }
  28.     }

  29.     private function labelDisplay_isTruncatedChangedHandler(event:Event):void
  30.     {
  31.         if (_explicitToolTip)
  32.             return;
  33.         
  34.         var isTruncated:Boolean = labelDisplay.isTruncated;
  35.         
  36.         // 如果label被截断,则以tooltip方式显示整个label
  37.         super.toolTip = isTruncated ? labelDisplay.text : null;
  38.     }

参考文献
1.Flex4中的皮肤(4):使用SkinPart约束Skin . http://blog.csdn.net/thinkinside/article/details/4635138
2.FLEX4 在Spark皮肤中定义与使用新的皮肤机制. http://bbs.9ria.com/thread-44441-1-1.html
3.Flex 4 皮肤功能介绍. http://www.smithfox.com/?e=34
4.Flex4 Skinning 2: 皮肤协议. http://www.cnblogs.com/spoony/archive/2010/11/03/flex4-skinning-part02-skinning-contract.html
5.http://opensource.adobe.com/svn/opensource/flex/sdk/trunk/frameworks/projects/spark/src/spark/skins/spark/ButtonSkin.mxml
6.http://www.fising.cn/docs/AS3_Reference/spark/components/supportClasses/ScrollBarBase.html#SkinPart:decrementButton
7.FLEX 4 SKINNING–皮肤中的动态元件.http://blog.lunastudio.cn/?p=218
8.Flex4 Skinning 4: 留言板示例.http://www.cnblogs.com/spoony/archive/2010/11/08/flex4-skinning-part04-notecard-demo.html
9.Flex4 Skinning 2: 皮肤协议.http://www.cnblogs.com/spoony/archive/2010/11/03/flex4-skinning-part02-skinning-contract.html

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

一套扁平化界面风格的flex 皮肤

意外在git上发现这个项目,似乎刚开始不久,部分控件的新皮肤似乎还没完成,不过个人感觉挺不错的。大家觉得呢? =》git地址:https://github.com/akamud/FlatSpark...
  • clschen
  • clschen
  • 2014年05月20日 20:52
  • 3360

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

利用Adobe Flash Catalyst CS5.5制作Flex组件皮肤(Button)实例

利用Adobe FlashCatalyst CS5.5制作Flex组件皮肤(Button)实例   下面是进行button皮肤制作的其中一个方法及步骤 注意事项:1、Catalyst5.5导出的fxp...
  • neil89
  • neil89
  • 2013年09月27日 10:27
  • 2805

FLEX4 TitleWindow 添加帮组按钮(最大化、最小化相同)使用皮肤更改

最近发现需求需要在每个flex弹出框口上有一个“问号”按钮,实现帮助功能。在网上搜了一下,对于flex3版本的通过override createChildren 方法来添加,但是由于项目是flex4版...
  • spyiu
  • spyiu
  • 2013年12月26日 09:58
  • 3129

GeneralSanguo工作笔记1——利用Illustrator制作Flex4皮肤

突兀的从服务端转到了客户端,有点意外也有点惊喜。工作几年了,暮然回首却发现自己竟然没有留下任何有价值的东西,很是遗憾。从今天起,我要将每一次成功或失败详细的记录下来,也算是记录自己的成长吧。目标:制作...

Flex4皮肤制作详解

在Flex4新增加了一个包:spark.skins,这个包里面只有一个类:SparkSkin,而我们(非美工的程序员)通过这个class来实现任意自定义控件的样式。通过上述关系可以得出如下的结论:1、...

定制Flex4组件外观皮肤

由于Flex4进行重构,Flex3里很多样式在flex4中无效,所以得重写flex4组件外观文件 Flex4之皮肤定制【Skin类和Skin类】 第一、关于spark.skin.SparkSkin...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:FLEX皮肤实例4_skinpart
举报原因:
原因补充:

(最多只允许输入30个字)