Skip to content

布局约束

规则

  1. 上层 widget 向下层 widget 传递约束条件
  2. 下层 widget 向上层 widget 传递大小信息
  3. 最后,上层 widget 决定下层 widget 的位置

严格约束和宽松约束

严格约束

严格约束是确切的大小,即它的最大/最小宽高是一致的

dart
BoxConstraints.tight(Size size)
   : minWidth = size.width,
     maxWidth = size.width,
     minHeight = size.height,
     maxHeight = size.height;

宽松约束

宽松约束设置了最大宽度/高度,但是让允许其子 widget 获得比它更小的任意大小

dart
BoxConstraints.loose(Size size)
   : minWidth = 0.0,
     maxWidth = size.width,
     minHeight = 0.0,
     maxHeight = size.height;

样例 1

dart
Container(width: 100, height: 100, color: red)

屏幕就是严格约束,会强制子变成和屏幕一样的大小。

虽然红色的 Container 想要变成 100 x 100 的大小,但是它无法变成,因为屏幕强制它变成和屏幕一样的大小

样例 2

dart
Center(
  child: Container(width: 100, height: 100, color: red),
)

Center 就是宽松约束

屏幕强制 Center 变得和屏幕一样大,所以 Center 充满了屏幕

然后 Center 告诉 Container 可以变成任意大小,但是不能超出屏幕。所以Container 可以真正变成 100 × 100 大小

样例 3

dart
Align(
  alignment: Alignment.bottomRight,
  child: Container(width: 100, height: 100, color: red),
)

Align 同样也告诉 Container,你可以变成任意大小,但是不能超出屏幕。所以Container 也变成 100 × 100 大小

样例 4

Container 的父组件为宽松约束Constainer 没有子组件,则它有多大就多大

dart
Center(
  child: Container(color: red),
)

屏幕强制 Center 变得和屏幕一样大,所以 Center 充满屏幕

然后 Center 告诉 Container 可以变成任意大小,但是不能超出屏幕。由于 Container 没有子级而且没有固定大小,所以它决定能有多大就有多大,所以它充满了整个屏幕

样例 5

Container 的父组件为宽松约束Constainer 有子组件,则它会变成它子组件的大小

dart
Center(
  child: Container(
    color: red,
    child: Container(color: green, width: 30, height: 30),
  ),
)

屏幕强制 Center 变得和屏幕一样大,所以 Center 充满屏幕

然后 Center 告诉红色的 Container 可以变成任意大小,但是不能超出屏幕。由于 Container 没有固定大小但是有子级,所以它决定变成它 child 的大小

然后红色的 Container 告诉它的 child 可以变成任意大小,但是不能超出屏幕

而它的 child 是一个想要 30 × 30 大小绿色的 Container。由于红色的 Container 和其子级一样大,所以也变为 30 × 30。由于绿色的 Container 完全覆盖了红色 Container,所以你看不见它了

ConstrainedBox

ConstrainedBox 可约束 4 个浮点类型的集合:最大/最小宽度,以及最大/最小高度

ConstrainedBox 会优先遵从它父级的约束,而后再根据接收到的约束,约束它的子级

样例 1

dart
ConstrainedBox(
  constraints: const BoxConstraints(
    minWidth: 70,
    minHeight: 70,
    maxWidth: 150,
    maxHeight: 150,
  ),
  child: Container(color: red, width: 10, height: 10),
)

屏幕迫使 ConstrainedBox 与屏幕大小完全相同,因此它告诉其子 Widget 也以屏幕大小作为约束,从而忽略了其 constraints 参数带来的影响

样例 2

dart
Center(
  child: ConstrainedBox(
    constraints: const BoxConstraints(
      minWidth: 70,
      minHeight: 70,
      maxWidth: 150,
      maxHeight: 150,
    ),
    child: Container(color: red, width: 10, height: 10),
  ),
)

Center 允许 ConstrainedBox 达到屏幕可允许的任意大小。 ConstrainedBoxconstraints 参数带来的约束附加到其子对象上

Container 必须介于 70 到 150 像素之间。虽然它希望自己有 10 个像素大小,但最终获得了 70 个像素(最小为 70)

UnconstrainedBox

UnconstrainedBox 会可以让子级是任意大小

UnconstrainedBox 本身还是受到父级约束的

样例 1

dart
UnconstrainedBox(
  child: Container(color: red, width: 20, height: 50),
)

屏幕强制 UnconstrainedBox 变得和屏幕一样大,而 UnconstrainedBox 允许其子级的 Container 可以变为任意大小

样例 2

dart
UnconstrainedBox(
  child: Container(color: red, width: 4000, height: 50),
)

屏幕强制 UnconstrainedBox 变得和屏幕一样大,而 UnconstrainedBox 允许其子级的 Container 可以变为任意大小

但子容器太大了,无法容纳在 UnconstrainedBox 中,因此 UnconstrainedBox 将显示溢出警告

样例 3

dart
OverflowBox(
  minWidth: 0.0,
  minHeight: 0.0,
  maxWidth: double.infinity,
  maxHeight: double.infinity,
  child: Container(color: red, width: 4000, height: 50),
)

OverflowBoxUnconstrainedBox 类似,但不同的是,如果其子级超出该空间,它将不会显示任何警告

样例 4

dart
UnconstrainedBox(
  child: Container(color: Colors.red, width: double.infinity, height: 100),
)

这将不会渲染任何东西,而且你能在控制台看到错误信息

UnconstrainedBox 让它的子级决定成为任何大小,但是其子级是一个具有无限大小的 Container

Flutter 无法渲染无限大的东西,所以它抛出以下错误: BoxConstraints forces an infinite width.(盒子约束强制使用了无限的宽度)

适应性布局

样例 1

Example 18 layout

dart
const FittedBox(
  child: Text('Some Example Text.'),
)

屏幕强制 FittedBox 变得和屏幕一样大,而 Text 则是有一个自然宽度(也被称作 intrinsic 宽度),它取决于文本数量,字体大小等因素

FittedBoxText 可以变为任意大小。但是在 Text 告诉 FittedBox 其大小后, FittedBox 缩放文本直到填满所有可用宽度

样例 2

Example 19 layout

dart
const Center(
  child: FittedBox(
    child: Text('Some Example Text.'),
  ),
)

Center 将会让 FittedBox 能够变为任意大小,取决于屏幕大小

FittedBox 然后会根据 Text 调整自己的大小,然后让 Text 可以变为所需的任意大小,由于二者具有同一大小,因此不会发生缩放

样例 3

Example 20 layout

dart
const Center(
  child: FittedBox(
    child: Text(
        'This is some very very very large text that is too big to fit a regular screen in a single line.'),
  ),
)

FittedBox 会尝试根据 Text 大小调整大小,但不能大于屏幕大小。然后假定屏幕大小,并调整 Text 的大小以使其也适合屏幕