Flutter完整开发实战详解(七、 深入布局原理)
在第六篇中我们知道了 Widget
、Element
、RenderObject
三者之间的关系,其中我们最为熟知的 Widget
,作为“配置文件”的存在,在 Flutter 中它的功能都是比较单一的,属于 “颗粒度比较细的存在” ,写代码时就像拼乐高“积木”,那这“积木”究竟怎么拼的?下面就 深入 去挖挖有意思的东西吧。( ̄▽ ̄)
一、单子元素布局
在 Flutter 单个子元素的布局 Widget 中,Container
无疑是被用的最广泛的,因为它在“功能”上并不会如 Padding
等 Widget 那样功能单一,这是为什么呢?
究其原因,从下图源码可以看出,Container
其实也只是把其他“单一”的 Widget 做了二次封装,然后通过配置来达到“多功能的效果”而已。
接着我们先看 ConstrainedBox
源码,从下图源码可以看出,它是继承了 SingleChildRenderObjectWidget
,关键是 override 了 createRenderObject
方法,返回了 RenderConstrainedBox
。
这里体现了第六篇中的 Widget 与 RenderObject 的关系
是的,RenderConstrainedBox
就是继承自 RenderBox
,从而实现RenderObject
的布局,这里我们得到了它们的关系如下 :
Widget | RenderObject |
---|---|
ConstrainedBox | RenderConstrainedBox |
然后我们继续对其他每个 Widget 进行观察,可以看到它们也都是继承SingleChildRenderObjectWidget
,而“简单来说”它们不同的地方就是 RenderObject
的实现了:
Widget | RenderBox (RenderObject) |
---|---|
Align | RenderPositionedBox |
Padding | RenderPadding |
Transform | RenderTransform |
Offstage | RenderOffstage |
所以我们可以总结:真正的布局和大小计算等行为,都是在 RenderBox
上去实现的。 不同的 Widget 通过各自的 RenderBox
实现了“差异化”的布局效果。所以找每个 Widget 的实现,找它的 RenderBox
实现就可以了。(当然,另外还有 RenderSliver
,这里暂时不讨论)
这里我们通过 Offstage
这个Widget 小结下,Offstage
这个 Widget 是通过 offstage
标志控制 child 是否显示的效果,同样的它也有一个 RenderOffstage
,如下图,通过 RenderOffstage
的源码我们可以“真实”看到 offstage
标志位的作用:
所以大部分时候,我们的 Widget 都是通过实现 RenderBox
实现布局的 ,那我们可不可抛起 Widget 直接用 RenderBox
呢?答案明显是可以的,如果你闲的