egret-docs-master/extension/EUI/autoLayout/layoutPrinciple/README.md

33 lines
3.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

自动布局本质上就是封装了各种更加便捷的相对布局属性,结合[失效验证机制](../../autoLayout/FailureToVerify/README.md),在合适的触发条件下(如尺寸发生改变时),自动设置相关对象的`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()`方法里实现。多个组件都需要测量的时候,会按照显式列表深度,从内向外测量。而布局阶段正好相反,从外向内。具体细节参考[失效验证机制](../../../../extension/EUI/autoLayout/FailureToVerify/README.md)的内容。
总之,如果希望自定义的组件像框架里的标准组件一样,能加入自动布局体系,就必须要同时重写`measure()`和`updateDisplayList()`方法。
`Group`是容器基类。它不负责具体的布局规则,而是做了一个解耦处理。增加`layout`属性,类型为`LayoutBase`。`Group`中的`measure()`和`updateDisplayList()`方法的内容为:
~~~ typescript
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`的组合的方式,来设置任意的布局。