布局管理

Catalogue   

基本概念

Widget的大小通过constraints来约束,它有minWidth、maxWidth、minHeight、maxHeight几个属性。

  • Tight constraints:紧约束,最大值和最小值相等的情况
  • Loose constraints:松约束,最大值和最小值不相等的情况
  • Unbounded constraints:maxWidth、maxHeight都设置为double.infinity

Flutter 中的 widget 由在其底层的 RenderBox 对象渲染而成。渲染框由其父级 widget 给出约束,并根据这些约束调整自身尺寸大小。约束是由最小宽度、最大宽度、最小高度、最大高度四个方面构成;尺寸大小则由特定的宽度和高度两个方面构成。

一般来说,从如何处理约束的角度来看,有以下三种类型的渲染框:

  • 尽可能大。比如 Center 和 ListView 的渲染框。
  • 与子 widget 一样大,比如 Transform 和 Opacity 的渲染框。
  • 特定大小,比如 Image 和 Text 的渲染框。

布局

Flutter 中有两种布局模型:

  • 基于 RenderBox 的盒模型布局。
  • 基于 Sliver ( RenderSliver ) 按需加载列表布局。

两种布局方式在细节上略有差异,但大体流程相同,布局流程如下:

  1. 上层组件向下层组件传递约束(constraints)条件。
  2. 下层组件确定自己的大小,然后告诉上层组件。注意下层组件的大小必须符合父组件的约束。
  3. 上层组件确定下层组件相对于自身的偏移和确定自身的大小(大多数情况下会根据子组件的大小来确定自身的大小)。

首先,上层 widget 向下层 widget 传递约束条件;
然后,下层 widget 向上层 widget 传递大小信息。
最后,上层 widget 决定下层 widget 的位置。

Widget 会通过它的 父级 获得自身的约束。约束实际上就是 4 个浮点类型的集合:最大/最小宽度,以及最大/最小高度。
然后,这个 widget 将会逐个遍历它的 children 列表。向子级传递 约束(子级之间的约束可能会有所不同),然后询问它的每一个子级需要用于布局的大小。
然后,这个 widget 就会对它子级的 children 逐个进行布局。(水平方向是 x 轴,竖直是 y 轴)。
最后,widget 将会把它的大小信息向上传递至父 widget(包括其原始约束条件)。