DirectSurface UIDirectSurface UI
开始使用
文档/核心概念

布局与约束

DirectSurface UI 的布局采用约束传递模型。父组件决定子组件能用多大空间,子组件在约束范围内返回自己的尺寸,父组件再决定子组件的位置。

基本流程

一次布局通常包含三步:

  1. 父组件把约束传给子组件。
  2. 子组件根据约束和自身内容计算 size
  3. 父组件设置子组件的 offset

这意味着子组件不能随意决定自己出现在页面上的位置。位置由父组件决定。

约束含义

约束通常包含:

  • 最小宽度。
  • 最大宽度。
  • 最小高度。
  • 最大高度。

如果最大宽度或最大高度是有限值,说明父组件希望子组件在这个范围内布局。如果是无限值,说明子组件可以按内容自然扩展。

常见布局关系

RenderStackPanel 会按方向顺序排列子组件,并根据权重分配剩余空间。

RenderDockPanel 会先布局停靠在上下左右的区域,剩余区域交给 fill 子组件。

RenderGridPanel 会按行列轨道分配空间,适合表单和结构化页面。

RenderScrollViewer 会给内容一个可滚动视窗,内容可以大于视窗。

何时需要重新布局

影响尺寸或位置的状态变化,需要触发布局:

markNeedsLayout()

典型场景:

  • 子节点数量变化。
  • 文本变化导致测量结果变化。
  • 展开或折叠内容。
  • 列宽、行高、面板尺寸变化。
  • 虚拟列表可视范围变化。

只影响颜色、hover、光标闪烁、选中背景等视觉状态时,通常只需要重绘。

性能原则

  • 布局中不要递归扫描不可见的大量节点。
  • 大列表、大树和大文档应只布局可视区域或增量区域。
  • resize 期间避免反复创建组件对象。
  • 不要在布局阶段调用外部业务请求或触发复杂状态变更。

常见错误

  • 子组件自己改全局坐标。
  • 在 paint 中修改会触发布局的状态。
  • 每次布局都重建整棵子树。
  • 外层和内层同时管理滚动,导致虚拟化失效。