布局
布局模式,有时简称为布局,是一种基于盒子与其兄弟和祖辈盒子的交互方式来确定盒子的位置和大小的算法。在 LCUI 中参与布局计算的数据包括 display 属性、定位属性、几何属性、盒模型、尺寸规则、布局规则等,这些数据的用途大致如下:
- 在布局开始前,组件的 display 属性、定位属性和几何属性会被用于计算盒模型和尺寸规则。
- 在布局开始时,组件的 display 属性、定位属性和尺寸规则用于选择合适的布局规则。
- 在布局时,布局算法会根据组件的盒模型计算其兄弟和祖辈组件位置和尺寸。
出于学习和开发成本上的考虑,LCUI 的布局引擎以网页浏览器为参考对象,实现了 CSS 布局中常见的几种布局模式,在大多数情况下,同一种布局模式在 LCUI 应用程序和网页浏览器中的效果是一样的,因此,你也可以通过学习 CSS 布局相关文档来加深对布局的理解。
本文假定你已经熟悉 CSS 布局技术,如果你对 CSS 布局技术还不熟悉,我们建议你阅读 MDN 上的文档:《CSS 布局 - 学习 Web 开发 | MDN》
在介绍布局模式之前,我们先深入了解一下这些数据的概念和实现细节。
盒模型
盒模型用于定义组件的布局和渲染参数,它由以下几个部分组成:
- Content box: 这个区域是用来显示内容,大小可通过
width
和height
属性设置。 - Padding box: 包围在内容区域外部的空白区域,大小通过
padding
相关属性设置。 - Border box: 边框盒包裹内容和内边距,大小通过
border
相关属性设置。 - Canvas box: 画布区域包裹了边框盒,与外边距区域重叠,它定义了组件在渲染时所使用的画布的大小,组件的阴影参数会影响它的大小,如果组件没有阴影,则它的大小与边框盒相同。
- Margin box: 这是最外面的区域,是盒子和其他元素之间的空白区域。大小通过
margin
相关属性设置。
如下图所示:
你可以通过组件对象中的 box 属性来访问这些区域,例如:
printf(
"content_box: (%f, %f, %f, %f)\n",
w->box->content.x, w->box->content.y,
w->box->content.width, w->box->content.height,
);
printf(
"border_box: (%f, %f, %f, %f)\n",
w->box->border.x, w->box->border.y,
w->box->border.width, w->box->border.height,
);
Display 属性
实现页面布局的主要方法是设定display
属性的值,它允许我们更改默认的显示方式。LCUI 目前支持 display
属性的三种值: block
、inline-block
、flex
,该属性的默认值是 block
。
定位
定位 (positioning) 能够让我们把一个组件从它原本在布局中应该在的位置移动到另一个位置。定位 (positioning) 并不是一种用来给你做主要界面布局的方式,它更像是让你去管理和微调界面中的一个特殊项的位置。
LCUI 仅支持以下三种定位:
- **静态定位(Static positioning):**默认定位,表示使用布局引擎计算好的位置。
- **相对定位(Relative positioning):**相对定位,它允许我们相对于布局引擎计算好的位置来移动组件,这对于微调和精准设计 (design pinpointing) 非常有用。
- **绝对定位(Absolute positioning):**将组件从布局中移出,不占据空间,通过指定组件相对于父组件的偏移来确定位置。该定位适用于精确控制组件位置,例如:让组件停靠在右上角、或是让组件随着鼠标移动。
注意,绝对定位在浏览器中是相对于元素的最近被定位祖先元素 (nearest positioned ancestor element),而在 LCUI 中是直属父组件。
尺寸规则
尺寸规则影响到组件的布局规则和布局后的实际尺寸,也会影响到子组件的尺寸规则,它在组件的样式计算和布局阶段会被重新计算。以下是这些规则的作用说明:
- **FIXED:**固定。表示尺寸属性可在布局前直接计算出确切的值,除了设置 100px 这类值外,父组件的尺寸规则是固定时也会采用该规则,因为在父组件尺寸已知的情况下,即便子组件的尺寸是百分比值或 auto 也能直接计算出来。
- **FILL:**填充。组件的尺寸将填满父组件内容区域。大多数情况下该规则都会转换为固定,因为根组件的尺寸规则必定是固定。
- **PERCENT:**百分比。表示在计算尺寸属性的值之前必须先计算出父组件尺寸的实际值,然后再按照百分比计算实际值。在父组件尺寸规则不为固定且尺寸属性为 50% 这类值时,会采用百分比规则。
- **FIT_CONTENT:**适应内容。表示在布局完后使用内容区域的尺寸作为实际值。该规则常用于组件的高度,因为在大多数情况下宽度是固定的,由内容撑开高度。当组件采用绝对定位或者显示方式为内联块(inline-block)时,它的宽高都会采用该规则。