本系列教程基于Flutter widget, 意在为Flutter 入门提供基础建设. 重点在讲解widget 的 用法,参数以及扩展.
适宜人群: 入门

引子

Align 是老生常谈的组件之一, 提到它. 大家首要印象肯定是这是一个控制对齐方式的组件. 确实, 我们从它的属性也可知道一二. alignment、widthFactor、heightFactor无一不再说明,它对控制对齐方式这一块似乎颇有建树.
image
本文希望由浅入深, 更深层次的挖掘其内部的可能性.

从Alignment谈起

Alignment 简单来说像是一个坐标系,它将复杂的父控件的约束范围描述为中心为原点, 以左右为 x 轴, 上下为 y 轴的坐标系. 在接触边的时候便为单位坐标.



我们取的原点其实就是 (0,0) , 左上角就是 (-1,-1) … 这样一来, Align 便有了定位任意位置的特性. 如果大家有写过 Android 的绝对布局, 那么对此应该是感触极深的.

20221208160101.png

heightFactor、widthFactor是什么

这两个属性将 Align 的宽高设置为子控件的宽高乘上系数, 取值只要是非负数即可. 也就是说 Align 本身除了受外部约束的控制, 同时也会根据内部子控件的大小来调节. 为什么这样设计呢? 我们假设说有一个 100*100 的蓝色 Container 并且有着居中的属性 .

1
2
3
4
5
6
Container(
height: 100,
width: 100,
color: Colors.blue,
alignment: Alignment.center,
),

image

我们在 Container 的内部放入一个 50* 50的黄色Container.

1
2
3
4
5
Container(
height: 50,
width: 50,
color: Colors.yellow,
),

image

它默认是居中的, 如果想让它左上角对齐, 只要在外部盒子改成 Alignment.topLeft即可. 但是这时, 我只希望它在内部75*75大小的地方左上角对齐. 此时, 我们将 widthFactor、heightFactor 设为 1.5. 那么, 黄色盒子外部的 Align 约束大小就变成了 75*75, 我们再将 Align 的 alignment 设为 topLeft 图形就变成了这个样子.

1
2
3
4
5
6
Align(
heightFactor: 1.5,
widthFactor: 1.5,
alignment: Alignment.topLeft,
child: 黄色盒子,
)

image
也就是说, 我们成功通过了 factor 属性改变了 Align 对外所需的约束大小. 通过这两个属性, 我们可以更方便的完成一些设计上的变化.

源码

Align 主要的绘制部分在 RenderPositiondBox . 这里值得参考的部分依然是 performLayout 部分. 因为 Align 更像是一个布局的组件, 我们自然要学习它布局方面的思维.
image
这里主要还是要根据是否有子控件来执行布局, 我们主要关注一下当Child != null 的时候, Align 具体的布局测量实现吧 ! 可以看到, 首先根据 _widthFactor、_heightFactor 来判断当前的布局是否要收缩约束. 如果需要的话, 则会根据 factor 来计算自身的 Size 大小, 否则会尽可能的撑大自身.

在计算好子控件和 Align 的 Size 之后, 会根据用户传入的 Alignemnt 来最终计算偏移量.

1
2
3
4
5
6
@protected
void alignChild() {
_resolve();
final BoxParentData childParentData = child!.parentData! as BoxParentData;
childParentData.offset = _resolvedAlignment!.alongOffset(size - child!.size as Offset);
}

实际上, 每个布局组件大概都有这种操作. 我们也可以学习这种操作来写出自己的定位组件, 屏幕前的你不妨试试哦~

结语

这里是WeninerIo😇

如果你对这次的技术分享感兴趣或者有什么疑惑🧐

不妨在评论区留言或私信🤪

或许这次的分享不是你所期待的😣

那就点个关注吧! ❤️

下次也许就是你想看的呢🫣?