1 | @immutable |
Element由Widget创建,子类实现时每次都是new一个新对象返回,所以一个Widget可以在多个地方使用而不会有冲突。
1 | /// RenderObjectWidgets provide the configuration for [RenderObjectElement]s, |
RenderObject是RenderObjectWidget创建
1 | abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin implements HitTestTarget { |
首先,上层 widget 向下层 widget 传递约束条件;
然后,下层 widget 向上层 widget 传递大小信息。
最后,上层 widget 决定下层 widget 的位置。
指定大小
1 | BoxConstraints.tight(Size size) |
限制了最大,可以在宽高可以在[0, max]之间
1 | BoxConstraints.loose(Size size) |
https://flutter.cn/docs/ui/layout/constraints
1 | Expanded( |
ConstrainedBox对应的RenderObject是RenderConstrainedBox
1 | @override |
说明ConstrainedBox的大小不会超过父级给它的边界
那么父级给了它什么样的边界呢
this.constraints来自上一级Expanded
1 | class Expanded extends Flexible { |
有时候,RenderObject需要在其子节点中存储一些数据,比如用于布局的一些参数,或者和其他子节点之间的关系。为此,Flutter提供了ParentData,用于存储父节点的一些信息。每个RenderObject都有这个成员变量,该成员在setupParentData方法中初始化。子类如果需要ParentData的某个子类,需要重写该方法,并在该方法中对ParentData进行初始化。
Expanded不提供RenderObject,它通过为子节点添加ParentData,让Expanded的父节点知道ConstraintBox如何布局,这就是为什么RenderObject树的数量和Widget数不是一一对应的。
1 | late final double minChildExtent; |
Center对应的performLayout
1 | @override |
顺便看下Center怎么定位子节点位置
1 | Offset alongOffset(Offset other) { |
按照这个思路可以把后面所有的布局例子都看一遍