在Flex中,界面中的各个组件可以随着浏览器的大小而重新排列位置,始终在浏览器中保持满屏显示的状态。我们将这种效果称为“布局”。

Flex框架实现了一套自己的布局框架。在Flex3中,可以使用HBox、VBox等进行布局管理;在Flex4中,可以使用spark.layouts包中的布局管理器,这个包的布局功能更加强大和灵活

那么,在Flash或者纯AS项目中,如何实现布局呢?

侦听舞台的Resize事件是解决这个问题的常用方法。但是如果布局比较复杂,就需要大量的代码来实现这些布局,使用侦听Resize事件的方法未免显得繁琐。于是,就有人实现了AS下的布局类或者布局框架。例如:senocular Layout classYahoo ASTRA Layout Utility等等。本文介绍的是BaseUI

BaseUI的中文资料较少,这一篇官方说明的译文,通过它大致可以了解BaseUI的工作方式和特点。本文则准备以实例的方式基于一个纯AS项目来介绍BaseUI的基本用法,这样更容易理解。

一、BaseUI基本使用

在下面的这段代码中,建立了一个BaseUI的实例,然后绘制了一个shape并加入到显示列表中,将其置于舞台右下角,与舞台边框间隔10像素。

几个注意点:

  1. 必须设定stage的scaleMode为NO_SCALE,以及设定align为TOP_LEFT,否则布局可能会不正常;
  2. BaseUI必须基于stage,虽然基于root也能工作,但是可能会导致布局不正常;
  3. 将元素加入BaseUI并不等于加入显示列表,因此还需要将元素自行加入显示列表中

效果(在浏览器中查看swf或下载后使用Flash Player播放):

源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
[SWF(width=500,height=300,backgroundColor=0xcccccc)]
public class BaseUITest extends Sprite
{
public function BaseUITest()
{
//绘制一个背景颜色以便于观察
graphics.beginFill(0xFFFFFF);
graphics.drawRect(0, 0, 500, 300);
graphics.endFill();
//必须设置scaleMode和align,否则在布局的时候会不正常
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
//绘制一个背景颜色以便于观察
graphics.beginFill(0xFFFFFF);
graphics.drawRect(0, 0, 500, 300);
graphics.endFill();
//必须设置scaleMode和align,否则在布局的时候会不正常
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
//基于stage建立一个布局
_baseUI = new BaseUI(this.stage);
//为布局添加一个布局元素
var __elementRB:ElementUI = _baseUI.add(createShape(this.stage));
//设置该布局元素距右边和下方各10像素,并刷新布局使其生效
__elementRB.right = 10;
__elementRB.bottom = 10;
__elementRB.refresh();
}
private var _baseUI:BaseUI;
//快速绘制一个Shape用于测试,如果绘制的时候提供了父显示对象,就将其加入父显示对象的显示列表
private function createShape($parent:DisplayObjectContainer=null):Shape
{
var __shape:Shape = new Shape();
__shape.graphics.lineStyle(2, 0xFF0000);
__shape.graphics.drawRect(0, 0 , 30, 30);
if($parent)
$parent.addChild(__shape);
return __shape;
}
}

二、可以使用几个BaseUI?

最开始,我以为BaseUI是可以用于其它的显示容器的,于是就做了个实验,建立一个Sprite并加入到stage中,并基于这个Sprite建立一个BaseUI,再使用这个新的BaseUI来控制Sprite的子显示对象。但发现这样做出来的布局无法正常显示。当然,可能是由于我遗忘了某些东西或者使用方法不正确,但我还是建议对于子容器使用com.soma.ui.layouts包。

三、HBoxUI的用法

HBox是一个横向布局容器,它继承自LayoutUI,而LayoutUI则继承自MovieClip(为什么是MovieClip而不是Sprite?这个我也不知道,我在源码中将LayoutUI的超类改为了Sprite,使用也一切正常)。

下面这段代码中建立了一个HBox容器,并为它增加了6个子显示对象,通过对HBox属性的设定,可以控制子显示对象的间隔以及在HBox中的对其方式。

几个注意点:

  1. backgroundAlpha属性默认是完全透明,因此如果要显示背景色,就必须将其设定为大于0的值;
  2. 因为LayoutUI是显示对象,因此可以直接将HBoxUI的实例加入显示列表,而ElementUI是不能加入显示列表的;
  3. 要获取LayoutUI的对应ElementUI,可以使用element属性;
  4. 不需要将LayoutUI加入到BaseUI的实例中,但需要为LayouUI传递stage,如果传递其它的容器,则可能会导致布局问题。

效果(在浏览器中查看swf或下载后使用Flash Player播放):

源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//增加一个HBox容器,设定背景色和透明度
var __hbox:HBoxUI = new HBoxUI(this.stage);
__hbox.backgroundColor = 0x0000FF;
//透明度默认是完全透明,所以必须设定才能让背景色显示出来
__hbox.backgroundAlpha = 0.2;
//让该容器置顶,宽度始终与舞台相同
__hbox.right = 0;
__hbox.left = 0;
__hbox.top = 0;
//让容器中的子显示对象的横向间隔为10像素
__hbox.childrenGap = new GapUI(10);
//让容器中的子显示对象基于容器的右下方对齐
__hbox.childrenAlign = HBoxUI.ALIGN_BOTTOM_RIGHT;
//加入6个shape
for(var i:int=0; i<6; i++)
{
createShape(__hbox);
}
//将容器加入显示列表并刷新容器布局
addChild(__hbox);
__hbox.refresh();

四、CanvasUI的用法

使用HBoxUI和VBoxUI可以实现横向和纵向的布局。但我们有时候需要布局更灵活一些。例如希望3个显示对象分别排列在容器的左、中、右,如何处理呢?

下面这段代码建立了一个CanvasUI容器,在容器中增加了3个shape,并实现左、中、右排列。

效果(在浏览器中查看swf或下载后使用Flash Player播放):

源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//增加一个CanvasUI容器
var __canvas:CanvasUI = new CanvasUI(this.stage);
__canvas.backgroundColor = 0xFF0000;
__canvas.backgroundAlpha = .5;
//让canvas在舞台中纵向居中,宽度与舞台宽度始终相同
__canvas.verticalCenter = 0;
__canvas.left = 0;
__canvas.right = 0;
//建立canvas的第1个子显示对象,在canvas中左下对齐
var __shape1:Shape = createShape();
var __element1:ElementUI = __canvas.add(__shape1);
__element1.left = 0;
__element1.bottom = 0;
//建立canvas的第2个子显示对象,在canvas中居中对齐
var __shape2:Shape = createShape();
var __element2:ElementUI = __canvas.add(__shape2);
__element2.horizontalCenter = 0;
__element2.verticalCenter = 0;
//建立canvas的第3个子显示对象,在canvas中右上对齐
var __shape3:Shape = createShape();
var __element3:ElementUI = __canvas.add(__shape3);
__element3.right =0;
addChild(__canvas);
__canvas.refresh();

五、全部源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
package
{
import com.soma.ui.BaseUI;
import com.soma.ui.ElementUI;
import com.soma.ui.layouts.CanvasUI;
import com.soma.ui.layouts.HBoxUI;
import com.soma.ui.vo.GapUI;
import flash.display.DisplayObjectContainer;
import flash.display.Shape;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
[SWF(width=500,height=300,backgroundColor=0xcccccc)]
public class BaseUITest extends Sprite
{
public function BaseUITest()
{
//绘制一个背景颜色以便于观察
graphics.beginFill(0xFFFFFF);
graphics.drawRect(0, 0, 500, 300);
graphics.endFill();
//必须设置scaleMode和align,否则在布局的时候会不正常
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
//基于stage建立一个布局
_baseUI = new BaseUI(this.stage);
//为布局添加一个布局元素
var __elementRB:ElementUI = _baseUI.add(createShape(this.stage));
//设置该布局元素距右边和下方各10像素,并刷新布局使其生效
__elementRB.right = 10;
__elementRB.bottom = 10;
__elementRB.refresh();
//增加一个HBox容器,设定背景色和透明度
var __hbox:HBoxUI = new HBoxUI(this.stage);
__hbox.backgroundColor = 0x0000FF;
//透明度默认是完全透明,所以必须设定才能让背景色显示出来
__hbox.backgroundAlpha = 0.2;
//让该容器置顶,宽度始终与舞台相同
__hbox.right = 0;
__hbox.left = 0;
__hbox.top = 0;
//让容器中的子显示对象的横向间隔为10像素
__hbox.childrenGap = new GapUI(10);
//让容器中的子显示对象基于容器的右下方对齐
__hbox.childrenAlign = HBoxUI.ALIGN_BOTTOM_RIGHT;
//加入6个shape
for(var i:int=0; i<6; i++)
{
createShape(__hbox);
}
//将容器加入显示列表并刷新容器布局
addChild(__hbox);
__hbox.refresh();
//增加一个CanvasUI容器
var __canvas:CanvasUI = new CanvasUI(this.stage);
__canvas.backgroundColor = 0xFF0000;
__canvas.backgroundAlpha = .5;
//让canvas在舞台中纵向居中,宽度与舞台宽度始终相同
__canvas.verticalCenter = 0;
__canvas.left = 0;
__canvas.right = 0;
//建立canvas的第1个子显示对象,在canvas中左下对齐
var __shape1:Shape = createShape();
var __element1:ElementUI = __canvas.add(__shape1);
__element1.left = 0;
__element1.bottom = 0;
//建立canvas的第2个子显示对象,在canvas中居中对齐
var __shape2:Shape = createShape();
var __element2:ElementUI = __canvas.add(__shape2);
__element2.horizontalCenter = 0;
__element2.verticalCenter = 0;
//建立canvas的第3个子显示对象,在canvas中右上对齐
var __shape3:Shape = createShape();
var __element3:ElementUI = __canvas.add(__shape3);
__element3.right =0;
addChild(__canvas);
__canvas.refresh();
this.stage.addEventListener(Event.RESIZE, handler_resize);
}
private var _baseUI:BaseUI;
//快速绘制一个Shape用于测试,如果绘制的时候提供了父显示对象,就将其加入父显示对象的显示列表
private function createShape($parent:DisplayObjectContainer=null):Shape
{
var __shape:Shape = new Shape();
__shape.graphics.lineStyle(2, 0xFF0000);
__shape.graphics.drawRect(0, 0 , 30, 30);
if($parent)
$parent.addChild(__shape);
return __shape;
}
private function handler_resize(evt:Event):void
{
trace(stage.stageWidth, stage.stageHeight, stage.width, stage.height);
}
}
}

留言

2010-12-19
次访问