区块链技术博客
www.b2bchain.cn

Flutter 布局:布局的整体流程求职学习资料

本文介绍了Flutter 布局:布局的整体流程求职学习资料,有助于帮助完成毕业设计以及求职,是一篇很好的资料。

对技术面试,学习经验等有一些体会,在此分享。

Flutter开发中,我们需要根据UI原形图构建代码,其中会碰到各种各样的布局要求,如对齐、排列等。Flutter也提供了各种基础的布局组件方便UI布局,然而我们必须先弄清楚Flutter布局的整体流程才能使用好这些组件。Flutter布局的整体流程最核心的就是做两件事:

  1. 确定组件的大小
  2. 确定组件的位置

那么Flutter是如何确定组件的大小和位置的呢。且看以下是一个UI原型图和它的widgets 树形图:

Flutter 布局:布局的整体流程

在 Flutter 中,几乎所有东西都是 widget,在UI布局中能直接看到的图标,文本是 widgets。不能直接看到的,用来排列、对齐等布局模型都是 widgets。并且所有的widgets都是以树形的结构关联起来的。在《Flutter 核心原理:Flutter帧渲染的整体流程》文章中已经介绍过,当Flutter绘制时会遍历绘制树(RenderObject Tree)然后进行Layout布局和Paint渲染这两个关键的步骤,树中组件的大小和位置正是在Layout这个步骤中确定的

上图中有个常用的布局组件Column,它是一个在垂直方向上排列子widget的布局组件。Column继承自Flex,其对应的RenderObject是RenderFlex。我们以Column组件为例,理一下布局的整体流程:

第一步:接收父组件的约束

在Layout开始时,从绘制树的根节点开始会调用每个子RenderObject的layout方法,传递Constraints约束给子节点。这就是所谓的上层 widget 向下层 widget 传递约束条件。同样Column组件也会接收到来自父组件Row传递过来的约束。

 // RenderObject 类的部分源码 // RenderFlex 的layout方法定义在父类RenderObject类中 // layout方法接收父组件传递过来的约束Constraints void layout(Constraints constraints, { bool parentUsesSize = false }) {   ...    _constraints = constraints;   ... } 

如上图代码所示,其中的Constraints就代表父组件给子组件的约束。其实就是由最小最大宽度和最小最大高度构成,总之就是为了控制子组件的大小。

第二步:遍历调用每一个子组件的layout方法

之前提到过绘制树从根节点开始遍历调用每一个子节点的layout。那么Column组件也需要负责遍历调用所有子节点的layout。

第三步:生成子组件的约束,通过layout传递约束

当Column组件接收到父组件的约束之后,它并不会原封不动的把这个约束传递给他的子组件,它会根据自己的逻辑需求生成合适的新的约束。然后在遍历子节点的时候通过调用子节点的layout方法传递新的约束。

第四步:获取子元素的size

当所有的子元素都完成了layout布局之后,Column组件就可以获取子元素的size了。这就是所谓的下层 widget 向上层 widget 传递大小信息

第五步:生成组件自身的size

组件自身的size是由父组件的约束和自身处理约束的方式这两个方面来决定的,有时候还需要获取子组件的size来配合进行计算。

现在我们以Column组件的 RenderFlex 部分源码为例,看一下它是如何完成以上步骤:


// RenderFlex类部分源码
@override
void performLayout() {
...
// 第一步:接收父组件的约束。 从父类RenderObject的layout方法中获得的。
final BoxConstraints constraints = this.constraints;
...
double crossSize = 0.0;
double allocatedSize = 0.0; // Sum of the sizes of the non-flexible children.
RenderBox? child = firstChild;
RenderBox? lastFlexChild;
// 第二步:遍历子节点
while (child != null) {
...
BoxConstraints innerConstraints;
if (crossAxisAlignment == CrossAxisAlignment.stretch) {
// 为子组件生成严格约束,要求子节点填满纵轴。
switch (_direction) {
case Axis.horizontal:
innerConstraints = BoxConstraints.tightFor(height: constraints.maxHeight);
break;
case Axis.vertical:
innerConstraints = BoxConstraints.tightFor(width: constraints.maxWidth);
break;
}
} else {
// 为子组件生成宽松约束,不强制要求子节点填满纵轴。
switch (_direction) {
case Axis.horizontal:
innerConstraints = BoxConstraints(maxHeight: constraints.maxHeight);
break;
case Axis.vertical:
innerConstraints = BoxConstraints(maxWidth: constraints.maxWidth);
break;
}
}
// 第三步:通过一定的逻辑,生成子组件的约束,通过子节点的layout方法传递约束。
child.layout(innerConstraints, parentUsesSize: true);
// 第四步:_getMainSize 和_getCrossSize 方法中可以看到。在child.layout之后就可以通过child.size.height或者child.size.width获取子组件的宽高。
// 通过子组件的宽高开始计算主轴和纵轴的size。
allocatedSize += _getMainSize(child);
crossSize = math.max(crossSize, _getCrossSize(child));
...

Flutter开发中,我们需要根据UI原形图构建代码,其中会碰到各种各样的布局要求,如对齐、排列等。Flutter也提供了各种基础的布局组件方便UI布局,然而我们必须先弄清楚Flutter布局的整体流程才能使用好这些组件。Flutter布局的整体流程最核心的就是做两件事:

  1. 确定组件的大小
  2. 确定组件的位置

那么Flutter是如何确定组件的大小和位置的呢。且看以下是一个UI原型图和它的widgets 树形图:

Flutter 布局:布局的整体流程

在 Flutter 中,几乎所有东西都是 widget,在UI布局中能直接看到的图标,文本是 widgets。不能直接看到的,用来排列、对齐等布局模型都是 widgets。并且所有的widgets都是以树形的结构关联起来的。在《Flutter 核心原理:Flutter帧渲染的整体流程》文章中已经介绍过,当Flutter绘制时会遍历绘制树(RenderObject Tree)然后进行Layout布局和Paint渲染这两个关键的步骤,树中组件的大小和位置正是在Layout这个步骤中确定的

上图中有个常用的布局组件Column,它是一个在垂直方向上排列子widget的布局组件。Column继承自Flex,其对应的RenderObject是RenderFlex。我们以Column组件为例,理一下布局的整体流程:

第一步:接收父组件的约束

在Layout开始时,从绘制树的根节点开始会调用每个子RenderObject的layout方法,传递Constraints约束给子节点。这就是所谓的上层 widget 向下层 widget 传递约束条件。同样Column组件也会接收到来自父组件Row传递过来的约束。

 // RenderObject 类的部分源码 // RenderFlex 的layout方法定义在父类RenderObject类中 // layout方法接收父组件传递过来的约束Constraints void layout(Constraints constraints, { bool parentUsesSize = false }) {   ...    _constraints = constraints;   ... } 

如上图代码所示,其中的Constraints就代表父组件给子组件的约束。其实就是由最小最大宽度和最小最大高度构成,总之就是为了控制子组件的大小。

第二步:遍历调用每一个子组件的layout方法

之前提到过绘制树从根节点开始遍历调用每一个子节点的layout。那么Column组件也需要负责遍历调用所有子节点的layout。

第三步:生成子组件的约束,通过layout传递约束

当Column组件接收到父组件的约束之后,它并不会原封不动的把这个约束传递给他的子组件,它会根据自己的逻辑需求生成合适的新的约束。然后在遍历子节点的时候通过调用子节点的layout方法传递新的约束。

第四步:获取子元素的size

当所有的子元素都完成了layout布局之后,Column组件就可以获取子元素的size了。这就是所谓的下层 widget 向上层 widget 传递大小信息

第五步:生成组件自身的size

组件自身的size是由父组件的约束和自身处理约束的方式这两个方面来决定的,有时候还需要获取子组件的size来配合进行计算。

现在我们以Column组件的 RenderFlex 部分源码为例,看一下它是如何完成以上步骤:


// RenderFlex类部分源码
@override
void performLayout() {
...
// 第一步:接收父组件的约束。 从父类RenderObject的layout方法中获得的。
final BoxConstraints constraints = this.constraints;
...
double crossSize = 0.0;
double allocatedSize = 0.0; // Sum of the sizes of the non-flexible children.
RenderBox? child = firstChild;
RenderBox? lastFlexChild;
// 第二步:遍历子节点
while (child != null) {
...
BoxConstraints innerConstraints;
if (crossAxisAlignment == CrossAxisAlignment.stretch) {
// 为子组件生成严格约束,要求子节点填满纵轴。
switch (_direction) {
case Axis.horizontal:
innerConstraints = BoxConstraints.tightFor(height: constraints.maxHeight);
break;
case Axis.vertical:
innerConstraints = BoxConstraints.tightFor(width: constraints.maxWidth);
break;
}
} else {
// 为子组件生成宽松约束,不强制要求子节点填满纵轴。
switch (_direction) {
case Axis.horizontal:
innerConstraints = BoxConstraints(maxHeight: constraints.maxHeight);
break;
case Axis.vertical:
innerConstraints = BoxConstraints(maxWidth: constraints.maxWidth);
break;
}
}
// 第三步:通过一定的逻辑,生成子组件的约束,通过子节点的layout方法传递约束。
child.layout(innerConstraints, parentUsesSize: true);
// 第四步:_getMainSize 和_getCrossSize 方法中可以看到。在child.layout之后就可以通过child.size.height或者child.size.width获取子组件的宽高。
// 通过子组件的宽高开始计算主轴和纵轴的size。
allocatedSize += _getMainSize(child);
crossSize = math.max(crossSize, _getCrossSize(child));
...

Flutter开发中,我们需要根据UI原形图构建代码,其中会碰到各种各样的布局要求,如对齐、排列等。Flutter也提供了各种基础的布局组件方便UI布局,然而我们必须先弄清楚Flutter布局的整体流程才能使用好这些组件。Flutter布局的整体流程最核心的就是做两件事:

  1. 确定组件的大小
  2. 确定组件的位置

那么Flutter是如何确定组件的大小和位置的呢。且看以下是一个UI原型图和它的widgets 树形图:

Flutter 布局:布局的整体流程

在 Flutter 中,几乎所有东西都是 widget,在UI布局中能直接看到的图标,文本是 widgets。不能直接看到的,用来排列、对齐等布局模型都是 widgets。并且所有的widgets都是以树形的结构关联起来的。在《Flutter 核心原理:Flutter帧渲染的整体流程》文章中已经介绍过,当Flutter绘制时会遍历绘制树(RenderObject Tree)然后进行Layout布局和Paint渲染这两个关键的步骤,树中组件的大小和位置正是在Layout这个步骤中确定的

上图中有个常用的布局组件Column,它是一个在垂直方向上排列子widget的布局组件。Column继承自Flex,其对应的RenderObject是RenderFlex。我们以Column组件为例,理一下布局的整体流程:

第一步:接收父组件的约束

在Layout开始时,从绘制树的根节点开始会调用每个子RenderObject的layout方法,传递Constraints约束给子节点。这就是所谓的上层 widget 向下层 widget 传递约束条件。同样Column组件也会接收到来自父组件Row传递过来的约束。

 // RenderObject 类的部分源码 // RenderFlex 的layout方法定义在父类RenderObject类中 // layout方法接收父组件传递过来的约束Constraints void layout(Constraints constraints, { bool parentUsesSize = false }) {   ...    _constraints = constraints;   ... } 

如上图代码所示,其中的Constraints就代表父组件给子组件的约束。其实就是由最小最大宽度和最小最大高度构成,总之就是为了控制子组件的大小。

第二步:遍历调用每一个子组件的layout方法

之前提到过绘制树从根节点开始遍历调用每一个子节点的layout。那么Column组件也需要负责遍历调用所有子节点的layout。

第三步:生成子组件的约束,通过layout传递约束

当Column组件接收到父组件的约束之后,它并不会原封不动的把这个约束传递给他的子组件,它会根据自己的逻辑需求生成合适的新的约束。然后在遍历子节点的时候通过调用子节点的layout方法传递新的约束。

第四步:获取子元素的size

当所有的子元素都完成了layout布局之后,Column组件就可以获取子元素的size了。这就是所谓的下层 widget 向上层 widget 传递大小信息

第五步:生成组件自身的size

组件自身的size是由父组件的约束和自身处理约束的方式这两个方面来决定的,有时候还需要获取子组件的size来配合进行计算。

现在我们以Column组件的 RenderFlex 部分源码为例,看一下它是如何完成以上步骤:


// RenderFlex类部分源码
@override
void performLayout() {
...
// 第一步:接收父组件的约束。 从父类RenderObject的layout方法中获得的。
final BoxConstraints constraints = this.constraints;
...
double crossSize = 0.0;
double allocatedSize = 0.0; // Sum of the sizes of the non-flexible children.
RenderBox? child = firstChild;
RenderBox? lastFlexChild;
// 第二步:遍历子节点
while (child != null) {
...
BoxConstraints innerConstraints;
if (crossAxisAlignment == CrossAxisAlignment.stretch) {
// 为子组件生成严格约束,要求子节点填满纵轴。
switch (_direction) {
case Axis.horizontal:
innerConstraints = BoxConstraints.tightFor(height: constraints.maxHeight);
break;
case Axis.vertical:
innerConstraints = BoxConstraints.tightFor(width: constraints.maxWidth);
break;
}
} else {
// 为子组件生成宽松约束,不强制要求子节点填满纵轴。
switch (_direction) {
case Axis.horizontal:
innerConstraints = BoxConstraints(maxHeight: constraints.maxHeight);
break;
case Axis.vertical:
innerConstraints = BoxConstraints(maxWidth: constraints.maxWidth);
break;
}
}
// 第三步:通过一定的逻辑,生成子组件的约束,通过子节点的layout方法传递约束。
child.layout(innerConstraints, parentUsesSize: true);
// 第四步:_getMainSize 和_getCrossSize 方法中可以看到。在child.layout之后就可以通过child.size.height或者child.size.width获取子组件的宽高。
// 通过子组件的宽高开始计算主轴和纵轴的size。
allocatedSize += _getMainSize(child);
crossSize = math.max(crossSize, _getCrossSize(child));
...

部分转自互联网,侵权删除联系

赞(0) 打赏
部分文章转自网络,侵权联系删除b2bchain区块链学习技术社区 » Flutter 布局:布局的整体流程求职学习资料
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

b2b链

联系我们联系我们