在Flutter中,小部件由底层RenderBox对象呈现。渲染框由其父项指定约束,并在这些约束内调整自身大小。约束包括最小和最大宽度和高度;尺寸由特定的宽度和高度组成。
根据处理约束的方式,通常有三种框:
- 那些试图尽可能大的人。例如,
Center和ListView使用的框。 - 那些试图和孩子一样大的人。例如,
Transform和Opacity使用的框。 - 那些试图达到特定尺寸的。例如,
Image和Text使用的框。
一些小部件,例如Container,根据它们的构造函数参数而类型而异。在Container的情况下,它默认尝试尽可能大,但如果您给它一个宽度,例如,它会尝试遵循该宽度并成为该特定大小。
其他的,例如Row和Column(弹性框)根据给定的约束而变化,如下面的“弹性”部分所述。
约束有时候是“紧”的,这意味着他们没有给渲染框留下决定尺寸的空间(例如,如果最小宽度和最大宽度相同,则称其具有紧宽度)。这方面的一个例子是App小部件,它包含在RenderView类中:应用程序的构建函数返回的子项使用的约束,强制它完全填充应用程序的内容区域(通常是整个屏幕)。
Flutter中的许多box,尤其是那些只带一个孩子的box,将它们的约束传递给他们的孩子。这意味着如果您在应用程序渲染树的根部将一堆盒子彼此嵌套,它们将完全适合彼此,受到哪些严格约束的强制。
一些盒子放宽了约束,这意味着最大值被保留但最小值被移除。例如,Center。
无限约束
在某些情况下,给盒子的约束是无界的或无限的。这意味着最大宽度或最大高度设置为double.infinity。
尝试尽可能大的框在给定无限约束时将无法正常运行,并且在调试模式下,这种组合会抛出指向该文件的异常。
渲染框发现自己具有无限约束的最常见情况是在弹性框(Row和Column)和可滚动区域(ListView和其他ScrollView子类)内。
特别是,ListView会尝试扩展以适应其横向的可用空间(例如,如果它是一个垂直滚动的块,它会尝试其父元素一样宽)。如果将垂直滚动的ListView嵌套水平滚动的ListView,则内部的会尝试尽可能宽,即无限宽,因为外部的可以在该方向滚动。
Flex
弹性框本身(Row和Column)根据它们在给定方向上是出于有界约束还是无界约束而表现不同。
在有界约束中,它们试图在那个方向上尽可能大。
在无限约束中,它们试图让孩子适应那个反方向。在这种情况下,您不能将子项的flex设置为0以外的任何值。在小部件库中,这意味着当弹性框位于另一个弹性框内或可滚动对象内,您不能使用Expanded。
在横向上,比如Column的宽度(vertical flex)或者Row的高度(horizontal flex),绝对不能是unbounded,否则就不能合理的对齐孩子们。