第四章 布局类
本章目录
- 4.1:布局类组件简介
- 4.2:线性布局(Row、Column)
- 4.3:弹性布局(Flex)
- 4.4:流式布局(Wrap、Flow)
- 4.5:层叠布局(Stack、Positioned)
- 4.6:对齐与相对定位(Align)
4.1 布局类组件简介
布局类组件都会包含一个或多个子组件,不同的布局类组件对子组件排版(layout)方式不同。我们在前面说过Element
树才是最终的绘制树,Element
树是通过Widget树来创建的(通过Widget.createElement()
),Widget其实就是Element的配置数据。在Flutter中,根据Widget是否需要包含子节点将Widget分为了三类,分别对应三种Element,如下表:
Widget | 对应的Element | 用途 |
---|---|---|
LeafRenderObjectWidget | LeafRenderObjectElement | Widget树的叶子节点,用于没有子节点的widget,通常基础组件都属于这一类,如Image。 |
SingleChildRenderObjectWidget | SingleChildRenderObjectElement | 包含一个子Widget,如:ConstrainedBox、DecoratedBox等 |
MultiChildRenderObjectWidget | MultiChildRenderObjectElement | 包含多个子Widget,一般都有一个children参数,接受一个Widget数组。如Row、Column、Stack等 |
注意,Flutter中的很多Widget是直接继承自StatelessWidget或StatefulWidget,然后在
build()
方法中构建真正的RenderObjectWidget,如Text,它其实是继承自StatelessWidget,然后在build()
方法中通过RichText来构建其子树,而RichText才是继承自MultiChildRenderObjectWidget。所以为了方便叙述,我们也可以直接说Text属于MultiChildRenderObjectWidget(其它widget也可以这么描述),这才是本质。读到这里我们也会发现,其实StatelessWidget和StatefulWidget就是两个用于组合Widget的基类,它们本身并不关联最终的渲染对象(RenderObjectWidget)。
布局类组件就是指直接或间接继承(包含)MultiChildRenderObjectWidget
的Widget,它们一般都会有一个children
属性用于接收子Widget。我们看一下继承关系 Widget > RenderObjectWidget > (Leaf/SingleChild/MultiChild)RenderObjectWidget 。
4.2 线性布局(Row和Column)
所谓线性布局,即指沿水平或垂直方向排布子组件。Flutter中通过Row
和Column
来实现线性布局,类似于Android中的LinearLayout
控件。Row
和Column
都继承自Flex
,我们将在弹性布局一节中详细介绍Flex
。
主轴和纵轴
对于线性布局,有主轴和纵轴之分,如果布局是沿水平方向,那么主轴就是指水平方向,而纵轴即垂直方向;如果布局沿垂直方向,那么主轴就是指垂直方向,而纵轴就是水平方向。在线性布局中,有两个定义对齐方式的枚举类MainAxisAlignment
和CrossAxisAlignment
,分别代表主轴对齐和纵轴对齐。
Expanded
可以按比例“扩伸” Row
、Column
和Flex
子组件所占用的空间。
const Expanded({
int flex = 1,
@required Widget child,
})
flex
参数为弹性系数,如果为0或null
,则child
是没有弹性的,即不会被扩伸占用的空间。如果大于0,所有的Expanded
按照其flex的比例来分割主轴的全部空闲空间
spacer
Spacer
的功能是占用指定比例的空间,实际上它只是Expanded
的一个包装类
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!