3.1 KiB
自动布局本质上就是封装了各种更加便捷的相对布局属性,结合失效验证机制,在合适的触发条件下(如尺寸发生改变时),自动设置相关对象的x
,y
,width
,height
等属性。所以无论过程是怎么样的,最终结果都是直接体现在x
,y
,width
,height
这些最原始的属性上,并没有脱离显示对象原始的API。
在上一节内容中,简单介绍了跟布局有关的两个方法:measure()
和updateDisplayList()
。本节详细说明这个两个方法:
updateDisplayList()
方法负责布局子项(即设置子项的x
,y
,width
,height
),或做一些矢量重绘操作。measure()
自动测量出当前适合子项的相关属性(width
,height
等)。
举个例子:有一个容器(Group),里面放一个单行文本(Label),想要文本始终在容器中水平居中(horizotalCenter = 0)。不需要显式设置文本的width
,这时measure()
会在文本内容改变时,自动测量出当前合适的width
,父级就会根据这个width
,重新布局它的x
,y
。
EUI 里所有的组件都是这样:如果不显式设置宽高,就调用measure()
方法测量出一个最佳尺寸,在没有被父级强制布局情况下,这个值最终赋值给width
和height
属性。反之,如果显式设置了组件的width
或height
属性,width
或height
就使用显式设置的值。若组件同时被设置了width
和height
,measure()
方法将不会被调用。至于何为测量的”最佳尺寸”?不同的组件有各自的测量方式,容器是能刚好放下所有子项的尺寸,文本是能完整显式文本内容的尺寸,而Image则是内部要显示的位图素材的尺寸。还有其他的组件,具体在各自的measure()
方法里实现。多个组件都需要测量的时候,会按照显式列表深度,从内向外测量。而布局阶段正好相反,从外向内。具体细节参考失效验证机制的内容。
总之,如果希望自定义的组件像框架里的标准组件一样,能加入自动布局体系,就必须要同时重写measure()
和updateDisplayList()
方法。
Group
是容器基类。它不负责具体的布局规则,而是做了一个解耦处理。增加layout
属性,类型为LayoutBase
。Group
中的measure()
和updateDisplayList()
方法的内容为:
protected measure():void {
if (!this.$layout) {
this.setMeasuredSize(0, 0);
return;
}
this.$layout.measure();
}
protected updateDisplayList(unscaledWidth:number, unscaledHeight:number):void {
if (this.$layout) {
this.$layout.updateDisplayList(unscaledWidth, unscaledHeight);
}
this.updateScrollRect();
}
Group
把自己的measure()
方法交给layout.measure()
实现,updateDisplayList()
交给layout.updateDisplayList()
实现。也就是把具体的布局方式解耦出来,形成独立的LayoutBase
类。这样所有的容器都可以采用Group+LayoutBase
的组合的方式,来设置任意的布局。