Flex 4 新体验


  直到最近才开始真正使用Flash Builder4来开发Flex应用。开始还是用Flex3的思想来进行开发,后来才逐渐发现原来自己Out了,完全没有用上Flex4的特性。下面仅说一下我用到的Flex4的新特性,当然这不全是Flex4所有新特性。
  1.Spark控件和Skin
  旧的控件仍然在mx命名空间之下,新增加的Spark控件体系也是在UIComponent基类扩展的。所以其根本并没有动摇,这样就可以在最大程度上使得mx控件和spark控件最大程度兼容。但是为什么要有Spark空间呢,而且多数都是与mx中原有控件一一对应的?目的只有一个那就是要将逻辑和样式分开。逻辑交给ActionScript负责,而样式则由Skin来负责。在Skin中可以利用各种flex4提供的绘图控件,如Path,Rect,Line等等,而有了这些就可以为控件提供背景色和边框等样式,因此Spark控件多数都没有mx控件所有的backgroundColor,border之类的style属性。
  你可以在这里找到关于Spark的架构。在spark体系中,增加Group这个常见的Container,这个有些类似于mx中的Box.因此可以想象会有类似VBox和HBox的VGroup和HGroup。Spark中的容器默认是BasicLayout,当然你可以设置为HorizantalLayout或者VerticalLayout。在给spark控件的Skin增加Rect或者Line的时候就要注意了,通常是在BasicLayout当中进行绘图,这样坐标才起作用,而在HorizantalLayout或者VerticalLayout则会影响你所设置的坐标。
  对于Spark中的Button等SkinableComponent是如何做到跟Skin结合的呢?我没有深入研究,但是根据一些粗浅的猜测可能是这样的:用Button来举例,利用FlexSpy观察出来,Button在显示的时候,它的子节点并不像原来那么单纯,可能就是一个label来显示文本,spark button的子节点却是一个ButtonSkin(注意Skin也是从UIComponent继承下来的),而在ButtonSkin的子节点下面才会有个Labe文本。因此当我们在ButtonSkin增加各种样式的时候也就反应到Button。在Button中你可以看到有一个labelDisplay的对象,也就是用于显示文本的Label,如果在ButtonSkin中我们不包含这个控件,则你的Button即使设置了label也不会显示任何东西。再提一点,这个labelDisplay在Button中会用SkinPart元素据标明,在Button源代码中你并没有看到labelDisplay被显示地创建。而在mx的button源代码中我们可以发现有一个textField在createChildren函数中被创建出来,它就是用来显示button的文本。那怎么将spark中Button的labelDispaly于Skin中的labelDisplay(注意这两者的名字必须一致)关联起来呢?你可以发现在SkinableComponent中有一个PartAdded的方法,而所有子类在继承该类的时候都会override这个方法以加入自己特定的SkinPart,如果存在SkinPart的话。顺着这个方法,你可以找到在该类的attachSkin方法会调用findSkinParts,而findSkinParts则会将Skin中定义的labelDisplay赋值给Button中定义的labelDisplay变量。但实际上这个labelDisplay控件还是Skin的子节点,而不是Button的子节点。
  还要注意对于SkinnableComponent来说存在两中不同的state,一个是控件本身的,如Button的down,up等状态,还有就是相应的ButtonSkin的down,up状态。这两者是不一样的。如果你设置了Button的状态,而不是更新了Skin的状态,那么你的Skin中不同状态的样式并不会起作用。SkinnalbeComponent中有一个方法是getCurrentSkinState,这个方法的返回值决定了Skin的State,因此你可以发现Button实际上覆盖了这个方法以返回Skin的不同状态。为了判断Skin的State,Button实际上是监听了MouseEvent,从而判断当前处于什么Skin State。为了真正使Skin State起作用,还需要调用invalidateSkinState方法。
  2.FXG
  定义了很多基本的图形如Rect, Line, Path等,对于fxg创建的控件你可以在MXML中直接引用。其实所有fxg控件都有对应的MXML控件。不过两者之间有个很重要的区别:MXML控件(如s:Rect, s:Line等)会在编译的时候转化为对应的ActionScript类,但是Fxg控件则会转成更低级别的flash player 指令。也就是说Fxg对应的控件为被优化,出于性能考虑可以尽量用fxg。从以下链接可以找到更多关于Fxg的有用信息。
  DataGroup会提供ItemRender,这个render比原来mx中datagrid的render有所改进,譬如可以得到data和itemIndex,而且可以赋值labelFunction。不过不能提供Skin。因此如果你想要用Skin的话就意味着你需要自己创建一个SkinableComponent,然后将它放入renderer。这样就遇到一个问题如何使得SkinnableComponent的Skin State会随着Renderer的state变化而变化。照理来说Renderer的State应该对应的是UIComponent的currentState,但是好像这个值也可以控制Renderer里面定义的样式,譬如可以设置某个Rect.includeIn="selected",这样选中的时候该Rect将显示。关于Renderer的State是个比较特殊的问题,你可以在官方文档中找到更多说明:http://help.adobe.com/en_US/flex/using/WS03d33b807 6db57b9-23c04461124bbeca597-8000.html#WS05A80398-9D D3-445a-BD33-A7D9FD695FA3
  itemRendererFunction也是一个好东西,你可以根据情况选择不同的ItemRenderer。对于
  With virtual layout disabled (useVirtualLayout=false), the DataGroup and SkinnableDataContainer containers create one instance of the item renderer for each child. With virtual layout enabled, the container only creates enough item renderers to display its currently visible children. Virtual layout greatly reduces the overhead required to use the DataGroup and SkinnableDataContainer containers.
  4.Css选择符
  可以支持子类选择等特性增加进来。我印象中这个原来就有了。具体我也不熟悉。但是有一点要提醒的是,如果你自定义了一个控件mycomp,在这个控件中引用了一个List,你想对这个List增加样式,并把样式设置为
  local|mycomp s|List{****}
  显然在mycomp里面引用该css,这样任何地方引用mycomp都可以得到一样的外观。但是实际上在mycomp中引用css文件的时候会报错,说什么List的选择符不支持。但是我们如果在Application下面引入该css就一切正常。原因没有深究,但是解决方案就是如果你要在mycomp中引用该css文件,那么就不要定义类型选择符,而是用类型选择符或者id选择符,如给List增加styleName="list",mycomp增加styleName="mycomp"
  .mycomp .list{*****}

猜你喜欢

转载自qr728qr.iteye.com/blog/1574458