乐趣区

关于前端:Flutter布局彻底搞懂-Align-是怎么对齐的

咱们在开发中会常常应用 Align 组件来定位子组件的地位。通常应用的是几个罕用的绝对地位,比方:alignment: Alignment.bottomRight,右下角这种。最近看官网文档对于 alignment: Alignment(x, y) 在 Align 中的计算解释如同有点不对,再联合相干的源码,总算是弄清楚了。而后发现网上的教程解释大多有谬误,上面就来分享下我对 Align 对齐原理的了解。

前置常识:Alignment

Alignment 的工作形式是先在一个矩形中建设一个虚构坐标系,这个虚构坐标系的原点是矩形的中点,而后 (x, y) 是在这个虚构坐标系中的定位点,并且规定了 (x, y) 的数值代表的是相对值,比方 Alignment(0.0, 0.0) 是中点,Alignment(1.0, 1.0) 是右下角,如图所示:

(x, y) 中的 x 这个相对值的单位是 矩形宽度的一半,比方 2.0 就相当于整个矩形宽度了;y 也是相似的,y 的单位是矩形高度的一半。

再通过一个公式转化为以矩形左上角为原点的坐标系中的定位点。这个转换公式如下:(x * w/2 + w/2, y * h/2 + h/2),其中 w 是矩形的宽度,h 是矩形的高度。联合上面的示意图来了解一下计算过程:

绿色框的是这个矩形,彩色坐标轴是虚构坐标系,蓝色坐标轴是以矩形左上角为原点的指标坐标系。以虚构坐标轴上横坐标 x 为例,转换后的指标点横坐标 x’ = 矩形宽度的一半 加上 x * 矩形宽度的一半(虚构坐标轴中 x 的单位是矩形宽度的一半)。

比方,Alignment(2.0, 0.0) 这个点转换后横坐标的值是 1.5 倍的矩形宽度,可不是两倍的矩形宽度喔。

Align 是怎么工作的

在 Align 的官网文档中有这样一句话:

How it works

The alignment property describes a point in the child‘s coordinate system and a different point in the coordinate system of this widget. The Align widget positions the child such that both points are lined up on top of each other.

意思是说,先利用 alignment 属性的形容求出在子组件坐标系的一个点和在 Align 组件坐标系中的另一个点;而后 Align 将子组件搁置在使这两个点重合的地位上。

谬误的解释

从以上形容能够看出,最初的搁置坐标是跟 Align 的大小也是有关系的,因为过程中要用 alignment 来计算 Align 中的一个点。但我从官网文档的示例阐明中只看到计算跟子组件相干:

并且我在网上看到的一些教程的解释,也是谬误的,比方这个:

要证实这个谬误很简略,将 Align 搁置在一个 Container 中,而后把 alignment 设置为 Alignment(1.0, 0.0),再轻易搁置一个子组件,比方这样:

Container(
  height: 120,
  width: 200,
  color: Colors.green.withOpacity(0.6),
  child: Align(alignment: Alignment(1.0, 0.0),
    child: Container(
      width: 60,
      height: 60,
      color: Colors.red,
    ),
  ),
),

你会发现不管怎么扭转里面 Container 的宽度,外面红色矩形的左边始终是和里面 Container 的左边是重合的。如果定位的坐标只与子组件的宽度相干,这是如何做到的呢?

我的了解

官网文档中 how it works 曾经给出了计算的原理,然而没有给出具体的公式。我看了下相干源码证实了 how it works 的形容是没有问题的,上面我用一个简略的例子来阐明下计算的过程,并给出正确的计算公式。

上图中绿色矩形是 Align 的大小,红色是子组件,我还是用 Alignment(1.0, 0.0) 来阐明。Alignment(1.0, 0.0) 所形容的点的横坐标在绿色矩形和红色矩形中都在左边框那里,如果 Align 依照这个地位来定位子组件的话,红色矩形应该在红色虚线框那里。但依据 how it works 的形容,Align 搁置子组件时会使两个点重合,也就是红色矩形左边框的点与绿色矩形左边框的点重合。这个时候咱们只须要从红色虚线框的地位挪动到实线框的地位,也就是:Align 中定位点的横坐标 减去 子组件中定位点的横坐标:

alignWidth / 2 + x * (alignWidth / 2) - childWidth / 2 - x * (childWidth / 2)

对于坐标的 y 值也能够用相似的过程来形容,所以最终定位点的计算公式应该是:

var x = (alignWidth - childWidth) / 2 + x * ((alignWidth - childWidth) / 2);
var y = (alignHeight - childHeight) / 2 + x * ((parentHeight - childHeight) / 2);

最初,如果 alignment 是 FractionalOffset 也能够用相似的过程来形容定位。FractionalOffset 与 Alignment 的不同在于虚构坐标系中 FractionalOffset 的原点在矩形左上角,并且 FractionalOffset(x, y) 中 x 的单位是矩形的整个宽度,不是一半。在 Align 中定位仍然遵循两个 FractionalOffset 的点要放弃重合。

退出移动版