59 lines
4.3 KiB
Plaintext
59 lines
4.3 KiB
Plaintext
// 测量/排列协商示例:arrange 指定子宽后需重新换行测量,高度变化继续影响父容器和后继位置,直到整树稳定。
|
|
// paragraph 被两个容器共享;每个 Mount 使用独立约束,不能把新宽度写回共享文字状态。
|
|
// 保存第一个段落出现位置的分配宽度,按钮只改策略值。
|
|
class Policy {
|
|
width: Number
|
|
// 选择 280 逻辑像素宽度,段落变高,后继文字下移。
|
|
// narrow/wide 按钮事件回调更新同一 policy.width,只有持有该策略的 ArrangedColumn 读取它。
|
|
function narrow(self: Policy, event: Event): Unit { self.width = 280 }
|
|
// 选择 560 逻辑像素宽度,段落变矮;另一个容器宽度不跟着改变。
|
|
function wide(self: Policy, event: Event): Unit { self.width = 560 }
|
|
}
|
|
// 在原生 Column 排列基础上覆盖第一个稳定子槽的宽度。
|
|
class ArrangedColumn: Column {
|
|
// 布局共享策略模型,不保存段落的全局最终宽度;某个出现的约束/分配由 Plan 独立记录。
|
|
policy: Policy
|
|
// 先取得包含全部子槽的 Arrangement,仅改第一子项分配;保留其他槽使排列验证完整。
|
|
function arrange(self: ArrangedColumn, mount: Mount, geometry: Bounds): Arrangement {
|
|
// source_layout 的安排阶段调用覆盖方法,基类利用本轮孩子测量值生成包含全部稳定 slot 的临时结果。
|
|
result = Column.arrange(self, mount, geometry)
|
|
// 只改返回的第一子槽 Bounds.width,宿主会验证槽完整性并据显式分配反推下一轮精确测量约束。
|
|
// at(0) 只用于挑选返回列表中的首项;该 Bounds 原有的稳定 slot 保持不变,宿主按 slot 而非列表下标关联孩子。
|
|
result.children.at(0).width = self.policy.width
|
|
return result
|
|
}
|
|
}
|
|
// 通过源 measure 改整个容器的期望宽度,以对比 arrange 分配路径。
|
|
class MeasuredColumn: Column {
|
|
// MeasuredColumn 自有策略字段,不是共享 paragraph 的 boxWidth,也不复制段落内容。
|
|
width: Number
|
|
// 调用原生测量后修改新结果 width;这个新结果不属于已有业务对象,允许在只读计算中填写。
|
|
function measure(self: MeasuredColumn, mount: Mount, constraints: Constraints): MeasureResult {
|
|
// 测量阶段先委托基类求自然尺寸,再修改临时 MeasureResult;已有业务对象仍受只读限制。
|
|
result = Column.measure(self, mount, constraints)
|
|
// 宿主读取这个新结果字段后还会按 Constraints 钳制;源返回 width 不等于绕过上层几何预算。
|
|
result.width = self.width
|
|
return result
|
|
}
|
|
}
|
|
// 两个容器使用同一个 paragraph,分别由 Policy=280 与 measure.width=360 约束。
|
|
policy = Policy(280)
|
|
paragraph = TextBlock("源码 arrange 改变分配宽度后,文字会按实际宽度重新测量。增加的高度继续影响容器和相邻对象,直到整棵布局稳定后才发布。这里与下面使用的是同一个 TextBlock;每个 Mount 都有自己的约束与几何。同一套内存对象不需要复制业务状态,也不通过丢弃传播来结束更新。")
|
|
tail = TextBlock("这一行跟随上方段落。")
|
|
// 首个孩子是 paragraph,故 at(0) 修改的是它的分配;tail 的位置在重新测高与收敛后随段落高度更新。
|
|
arranged = ArrangedColumn(0, 12, paragraph, tail, policy)
|
|
// 另一出现仍用同一 paragraph,但父测量策略为 360,与上面的 policy.width 独立。
|
|
measured = MeasuredColumn(0, 12, paragraph, TextBlock("这一段的宽度来自源码 measure。"), 360)
|
|
narrow = Button("arrange 为 280")
|
|
wide = Button("arrange 为 560")
|
|
// 保留事件订阅引用,两个按钮调用同一 Policy 的不同方法。
|
|
narrowConnection = narrow.on("click", policy.narrow)
|
|
wideConnection = wide.on("click", policy.wide)
|
|
// 这两个父容器都在同一文档根,布局需要整树稳定再一起发布,不能先显示新宽度再补旧高度。
|
|
page = Page()
|
|
page.title = "约束协商"
|
|
page.render(Column(24, 16, Row(0, 12, narrow, wide), arranged, measured))
|
|
// 成功输入结束后宿主才消费原生窗口命令;窗口实际尺寸再回传为下一次布局约束。
|
|
ui.window().resize(850, 700)
|
|
ui.window().setTitle("测量与排列直到稳定")
|