# Layout 与 Relative 模型

> CrossFly 如何测量与定位 —— 默认相对 —— 以及为什么这是响应式的基础。

Source: https://crossfly.dev/zh/docs/concepts/the-layout-and-relative-model — CrossFly documentation. Full docs as one file: https://crossfly.dev/llms-full.txt

# Layout 与 Relative 模型

CrossFly **默认是相对的，而非绝对的**。理解这一点就能明白为什么你的屏幕会
自行适配不同的尺寸、密度和旋转方向。

## 布局契约
每个容器都把子元素的组织委派给一个 `Layout`。这个级联的循环始终是：

**测量 → 定位 → 向子元素传播 `onLayout`。**

当布局失效时（尺寸、内容或旋转发生变化），框架会从根开始重做
这个循环。你无需手动重算位置 —— 你声明**意图**，由 `Layout` 去求解。

## 布局的谱系（按意图）
- **堆叠**（垂直/水平）→ `VerticalLayout` / `HorizontalLayout`
- **按分数的网格** → `GridLayout`
- **将一个组件锚定到另一个** → `RelativeLayout`
- **均匀分隔** → `EvenlySpacedLayout`
- **自由定位** → `RandomLayout`

更换容器的 `Layout` 可以在不改动子元素的情况下改变排布 —— 这正是使响应
旋转变得轻而易举的原因。（操作指南见 [布局](/docs/ui/layouts)。）

## 概念的核心：`Relative`
尺寸和位置不是固定像素 —— 而是**关系**。四种形式：

| 形式 | 含义 | 随之缩放 |
|---|---|---|
| `Relative.ofFont(1.5f)` | **字体高度**的分数 | UI 的缩放/密度 |
| `Relative.ofScreen(0.8f[, ScreenSize])` | **屏幕**的分数 | 屏幕尺寸 / 方向 |
| `LAY_FILL` / `LAY_AUTO` / 分数 | **容器**的分数 | 父级的尺寸 |
| `Relative.ofPixels(24f)` | **绝对像素** | 无（仅在例外情况使用） |

而 `Gap`（内边距 `ingap` / 外边距 `outgap`）遵循同样的逻辑：`Gap.ofFont(...)` 一同缩放。

```java
// header（内容高度）、content（吸收剩余空间）、footer（内容）— 在 VerticalLayout 中：
tela.add(LAY_AUTO, header);
tela.add(LAY_FILL, conteudo);   // 那个「弹性体」
tela.add(LAY_AUTO, footer);
```

## 为什么这是响应式的基础
如果**没有到处散布的固定像素**，框架就能在每次 resize、旋转或
缩放变化时**重算一切** —— 屏幕便会自动重新适配。响应式不是一个独立的功能：它是
按关系测量的自然结果。

> 黄金法则：把尺寸写成 `Relative`/分数/`LAY_FILL`；把 `ofPixels` 留给
> 确实固定的场景。一个固定像素是在赌屏幕永远不会变 —— 而它总是会变。

## 参见
- 应用：[布局](/docs/ui/layouts) · [响应式](/docs/ui/layouts/responsiveness)
- 下一篇：[样式与主题](/docs/concepts/styling-and-theming-model)
