所以 MultiChildRenderObjectElement 利用 ContainerRenderObjectMixin 最终将我们自定义的 RenderBox 和 Widget 关联起来。
6、自定义流程
上述主要描述了 MultiChildRenderObjectWidget 、 MultiChildRenderObjectElement 和其他三个辅助类ContainerRenderObjectMixin 、 RenderBoxContainerDefaultsMixin 和 ContainerBoxParentData 之间的关系。
了解几个关键类之后,我们看一般情况下,实现自定义布局的简化流程是:
1、自定义 ParentData 继承 ContainerBoxParentData 。
2、继承 RenderBox ,同时混入 ContainerRenderObjectMixin 和 RenderBoxContainerDefaultsMixin 实现自定义RenderObject 。
3、继承 MultiChildRenderObjectWidget,实现 createRenderObject 和 updateRenderObject 方法,关联我们自定义的 RenderBox。
4、override RenderBox 的 performLayout 和 setupParentData 方法,实现自定义布局。
当然我们可以利用官方的 CustomMultiChildLayout 实现自定义布局,这个后面也会讲到,现在让我们先从基础开始, 而上述流程中混入的 ContainerRenderObjectMixin 和 RenderBoxContainerDefaultsMixin ,在 RenderFlex 、RenderWrap 、RenderStack 等官方实现的布局里,也都会混入它们。
自定义布局就是在 performLayout 中实现的 child.layout 大小和 child.ParentData.offset 位置的赋值。
首先我们要实现类似如图效果,我们需要自定义 RenderCloudParentData
继承 ContainerBoxParentData
,用于记录宽高和内容区域 :
class RenderCloudParentData extends ContainerBoxParentData {
double width;
double height;
Rect get content => Rect.fromLTWH(
offset.dx,
offset.dy,
width,
height,
);
}
然后自定义 RenderCloudWidget
继承 RenderBox
,并混入 ContainerRenderObjectMixin
和 RenderBoxContainerDefaultsMixin
实现 RenderBox
自定义的简化。
class RenderCloudWidget extends RenderBox
with
ContainerRenderObjectMixin<RenderBox, RenderCloudParentData>,
RenderBoxContainerDefaultsMixin<RenderBox, RenderCloudParentData> {
RenderCloudWidget({
List children,
Overflow overflow = Overflow.visible,
double ratio,
}) : _ratio = ratio,
_overflow = overflow {
///添加所有 child
addAll(children);
}
如下代码所示,接下来主要看 RenderCloudWidget
中override performLayout
中的实现,这里我们只放关键代码:
-
1、我们首先拿到
ContainerRenderObjectMixin