跳到主要内容

布局组

布局组自动定位和调整子元素尺寸,支持单行、单列和换行形成的网格。适用于列表、工具栏、菜单、背包等需要在添加、移除和改尺寸时保持整齐排列的内容。

三种布局:行宽拉满父项的垂直列表、按钮均分宽度的工具栏,以及末行居中的方格网格;最浅颜色子项最先排列

创建布局组​

布局组组件与 Element 位于同一实体上,通常搭配组元素,其矩形就是布局空间。以下列表从上到下堆叠五行,并将各行拉伸到列表宽度:

const list = new pc.Entity('list');
list.addComponent('element', {
type: pc.ELEMENTTYPE_GROUP,
anchor: [0.5, 0.5, 0.5, 0.5],
pivot: [0.5, 0.5],
width: 300,
height: 400
});
list.addComponent('layoutgroup', {
orientation: pc.ORIENTATION_VERTICAL,
spacing: [0, 10],
padding: [10, 10, 10, 10],
widthFitting: pc.FITTING_STRETCH
});
screen.addChild(list);

for (let i = 0; i < 5; i++) {
const row = new pc.Entity(`row ${i}`);
row.addComponent('element', {
type: pc.ELEMENTTYPE_IMAGE,
height: 60,
color: new pc.Color(0.23, 0.55, 1)
});
list.addChild(row);
}

创建应用时注册 pc.LayoutGroupComponentSystem 和 pc.LayoutChildComponentSystem。即使没有子项使用 LayoutChild,布局组也需要其系统。

子项放置规则​

布局组按层级顺序排列启用且具有已启用 Element 的直接子项,对各子项执行:

  • 设置锚点为组左下角 0, 0, 0, 0。子项原有锚点,无论是否分离,都会被替换。
  • 设置位置。 根据子项轴心放置矩形,使不同轴心下矩形仍处于相同位置。
  • 设置计算尺寸。 适配或 LayoutChild 改变尺寸时,子项 width 和 height 仍保留设置值,作为起始尺寸;实际值详见宽度与高度。

更深层后代不受影响,因此各子项可以容纳自己的内容,甚至独立布局组。嵌套布局组从外向内布局。

子项添加、移除、启用、禁用、改尺寸或轴心变化,以及布局组属性变化时,会在同一帧稍后、绘制前重新布局。手动移动子项不会触发布局,下次布局会将其移回。每次布局后会触发带子项边界的 reflow:

list.layoutgroup.on('reflow', ({ bounds }) => {
// bounds.x and bounds.y are the bottom-left corner of the children, relative to the
// bottom-left corner of the group, and bounds.z and bounds.w are their width and height
console.log(`The children take up ${bounds.z} × ${bounds.w}`);
});

布局组属性​

方向​

Horizontal 从左到右排成行,Vertical 从上到下排成列。

反转​

Reverse X 和 Reverse Y 反转各轴顺序。默认启用 Reverse Y,使列和网格行从上到下排列。关闭可从底部向上,启用 Reverse X 可从右向左。

对齐​

Alignment 决定未填满组时,子项整体的位置,从左下 0, 0 到右上 1, 1。默认 0, 1 为左上。网格中还控制每行对齐,因此 0.5, 1 可使不足一整行的末行居中。

内边距​

Padding 为组边缘内部保留空间,顺序为左、下、右、上。

间距​

Spacing 为相邻子项间隙。X 是同行子项间距,Y 是同列子项及网格行之间的间距。

尺寸适配​

Width Fitting 和 Height Fitting 决定是否调整子项尺寸以适应组:

适配模式子项行为
None保持自身尺寸
Stretch小于组时扩展填满,但不超过最大尺寸
Shrink大于组时缩小,但不低于最小尺寸
Both按需要拉伸或收缩

沿布局方向,例如一行的宽度,空余空间或溢出量在子项之间分摊,默认均分,可由布局子项指定不同权重。垂直于布局方向,各子项独立适应所在行高或列宽。引擎常量为 pc.FITTING_NONE、pc.FITTING_STRETCH、pc.FITTING_SHRINK 和 pc.FITTING_BOTH。

换行​

启用 Wrap 后,超出行宽的子项移到新行,形成网格。组宽决定每行数量:三个宽 100、间距 10 的子项,至少需要 320 宽。垂直布局则由组高决定每列数量。

布局子项​

为布局组子项添加 LayoutChild,可改变其尺寸分配:

属性效果
Min Width、Min Height布局允许的最小尺寸
Max Width、Max Height布局允许的最大尺寸,留空表示无限制
Fit Width Proportion、Fit Height Proportion拉伸或收缩时的空间分配权重。拉伸时,权重 2 获得权重 1 两倍的额外空间;收缩时,权重越大,缩减越少。例如两个宽 100、权重分别为 2 和 1 的子项缩入 140 单位后,宽度为 80 和 60
Exclude from Layout排除该子项,保留自己的锚点和位置

例如,工具栏按钮横向拉满时,可用最大宽度限制其中一个继续变大:

button.addComponent('layoutchild', {
maxWidth: 120
});

布局示例​

本页顶部图中的布局使用以下属性:

属性垂直列表工具栏网格
OrientationVertical(垂直)Horizontal(水平)Horizontal(水平)
Alignment0, 10, 0.50.5, 1
Padding10, 10, 10, 1010, 10, 10, 100, 0, 0, 0
Spacing0, 1010, 010, 10
Width FittingStretch(拉伸)Stretch(拉伸)None(无)
Height FittingNone(无)Stretch(拉伸)None(无)
Wrap关闭关闭开启
  • 垂直列表。 各行只设置高度,Width Fitting 将宽度拉伸到列表宽减内边距,适合排行榜和设置菜单。
  • 工具栏。 两轴拉伸,将工具栏宽度均分给按钮,并使高度适应内边距后的空间,按钮增减时仍保持均匀。
  • 网格。 子项为 100 单位方形,组宽 320,每行可放三个。0.5, 1 使网格从顶部开始,且每行居中,包括不足一整行的末行。
布局组

运行时修改布局​

修改布局组属性会重新排列子项。向量属性需要赋予新的向量对象:

list.layoutgroup.spacing = new pc.Vec2(0, 20);
list.layoutgroup.padding = new pc.Vec4(20, 20, 20, 20);
list.layoutgroup.wrap = true;

添加、移除、启用和禁用子项也会重新布局,因此列表会随条目增加而增长:

const row = new pc.Entity('row');
row.addComponent('element', {
type: pc.ELEMENTTYPE_IMAGE,
height: 60
});
list.addChild(row);

布局组不会自动调整自身元素尺寸以容纳子项。要让滚动视图内容适应列表,应使用 reflow 返回的边界。

另请参阅​