Flex 3.x到Flex 4.5 容器与布局组件
容器(Container)
在说布局之前,我们先说说Flex4中得容器的变化。Flex4中提供了一些新的容器,并且不在推荐使用Flex3中的容器了。
Group (包括HGroup、VGroup、TileGroup) 与DataGroup
SkinnableContainer、SkinnableDataContainer、Panel、TitleWindow、NavigatorContent、BorderContainer, 和Application(Panel、TitleWindow、NavigatorContent以及BorderContainer都是SkinnableContainer的子类)
当然Spark容器都具有以下特点:
可变的布局:除了部分已经自定义布局的容器(如HGroup、VGroup、TileGroup)的布局不能改变,其他的Spark容易都可以改变其布局,在本节后面做详细介绍Spark布局;
皮肤:我们知道Spark容器的皮肤和Flex3中的皮肤已经有很大的不同了,大部分的Spark容器都支持皮肤,当然这些容器得继承SkinnableContainer或者SkinnableDataContainer;但是为了提高性能及减小应用的大小,不是所有的容器都支持皮肤,如果容器没有继承自这两个Skinable类之一,那么他就不支持皮肤,如Group、DataGroup;
添加的子控件(Element/Child):DisplayObject、UIcomponent、Container、IVisualElement、IGraphicElement、IVisualElementContainer、ISharedDisplayObject。这几个类型,有些是在Spark中引入的新的类型,在后面我将详细的说一说他们的作用以及之间的关系,包括和Flex3 Halo之间的联系等。【传送门待添加】
下面列出一些Flex官方推荐的与Flex3的容器的映射关系,但是我们用的时候却不一定需要按照这个来:
Flex 3 Flex 4 (Spark)官方建议 实际应用备选建议
mx.containers.Canvas spark.components.BorderContainer spark.components.Group
mx.containers.Box spark.components.BorderContainer spark.components.Group
mx.containers.HBox spark.components.BorderContainer spark.components.HGroup
mx.containers.VBox spark.components.BorderContainer spark.components.VGroup
mx.containers.Panel spark.components.Panel spark.components.Panel
mx.containers.Tile spark.components.BorderContainer spark.components.Group(使用TileLayout)
mx.containers.TitleWindow spark.components.TitleWindow spark.components.TitleWindow
mx.containers.Form spark.components.Form spark.components.Form
上面的表格中有很多地方都可以用BorderContainer或者是Group,是不是感到困惑呢?从前面的一段话中可以看出,Group是没有Skin的,BorderContainer是有Skin的,所以在使用的时候可以根据自己的需求,由于Layout已经可以自己设定,那么只需要看是否使用Skin,就可以决定究竟是使用BorderContainer还是Group。另外还有很多具体的变化,从Flex3刚转到Flex4,可能知道上面的对应关系还不够,还有很多细节,如clipping、scrollbar等问题,我会在讲解Skin的一篇说说clipping、scrollable以及如何给自定义Container。
布局(Layout)
Flex4/Spark组件架构的新功能之一是可以定制一个容器的布局而不必改变容器本身,正如前面提到的“可变的布局”,默认的有BasicLayout、HorizontalLayout、TileLayout、VerticalLayout四大布局方式。
基本布局
BasicLayout:这是spark组件默认的布局方式,即绝对定位布局。在FlexSDK3里面对应的是:layout=”absolute”;类似Flex3中的Canvas的布局;
HorizontalLayout:这是spark组件库里面的水平布局方式。在里面对应的是:layout=”horizontal”;对应Flex3中得HBox的布局方式;
VerticalLayout:这是spark组件库里面的竖直布局方式。在FlexSDK3里面对应的是:layout=”vertical”;对应Flex3中得VBox的布局;
TileLayout:这是spark组件库新增的布局方式,即格子布局方式。TileLayout布局方式可以说是HorizontalLayout和VerticalLayout结合的方式;当然可以看出这就是Flex3中得Tile组件的布局方式。
布局使用方法
我们仍然分别使用MXML和ActionScript两种方式来举例说明。首先来说最常用的方式,也就是MXML的方式:
<s:Group>
<s:layout>
<s:HorizontalLayout />
</s:layout>
</s:Group>
例子中用的是HorizontalLayout,当然,你可以使用其他的Layout。
<fx:Script>
<![CDATA[
import mx.core.LayoutDirection;
import mx.events.FlexEvent;
import spark.layouts.HorizontalLayout;
protected function creationCompleteHandler(event:FlexEvent):void {
group.layout = new HorizontalLayout;
//group.layoutDirection = LayoutDirection.LTR;
}
]]>
</fx:Script>
<s:Group layoutDirection="rtl">
<s:Button label="A" />
<s:Button label="B" />
</s:Group>
当然,在上面的代码中除了设置layout,还设置了layoutDirection,这是在4.1中加入的属性,用来指定布局方式是从左往右(ltr)还是从右向左(rtl),也可以像注视中的AS代码那样设置。
Layout的属性设置
另外,Flex3中,我们可以在Container上设置设置的与布局相关的属性现在都移到了layout上,比如verticalAlign、horizontalAlign、gap以及各个方向的padding值:
<s:Group layoutDirection="rtl">
<s:layout>
<s:HorizontalLayout verticalAlign="baseline" horizontalAlign="left" gap="5" paddingBottom="1" paddingLeft="1" paddingRight="1" paddingTop="1" />
</s:layout>
<s:Button label="A" />
<s:Button label="B" />
</s:Group>
对于这些属性基本与Flex3中得相同,只是现在是针对layout设置了。另外layout还有一些在Flex中没有见过的属性,我们特别说下面两个:clipAndEnableScrolling、useVirtualLayout,他们的设置方法和gap、padding之类的属性一样设置:
clipAndEnableScrolling: 如果是true,则将超出范围的children裁掉不显示出来,如Flex3中得Canvas等,如果显示的范围超出了Canvas的范围,则不会显示;如果是false,则不管他的children是否超出他的范围,都会完全显示出来(但不会超出Application的范围)。
Flex4中有两个地方可以设置这个属性,一个是Skin中(该属性是定义在GroupBase中的property,而Skin继承GroupBase),一个是Layout中,而默认情况GroupBase中的property也是由Layout中取出,如下贴出SDK中GroupBase.get clipAndEnableScrolling的代码:
public function get clipAndEnableScrolling():Boolean {
if (_layout) {
return _layout.clipAndEnableScrolling;
}
else if (_layoutProperties && _layoutProperties.clipAndEnableScrolling !== undefined)
{
return _layoutProperties.clipAndEnableScrolling;
}
else{
return false;
}
}
由此我们可以看出,该属性在layout中设置才是合情理的。
useVirtualLayout:顾名思义是虚拟布局,那么虚拟布局是什么概念呢?我想我还是从它的用途说起吧。如果你熟悉Flex3中List的ItemRenderer的渲染机制,那么我们就当作Flex3中的List就是useVirtualLayout的效果。啥意思呢?当开启useVirtualLayout(设为true)之后,并不是所有的children都会被渲染,而是只有当前能够显示出来的child才会被渲染(比如List只显示一些itemRenderer,其他的通过Scrollbar控制)。
显然,这样我们可以大幅度的提高效率。