We often use the Align component in development to locate the position of the child components. Several commonly used relative positions are usually used, such as: alignment: Alignment.bottomRight
, the lower right corner. Recently, I read the official document about alignment: Alignment(x, y)
The calculation explanation in Align seems to be a bit wrong. Combined with the relevant source code, I finally figured it out. Then I found that most of the online tutorial explanations are wrong. Let me share my understanding of the Align alignment principle.
Prerequisites: Alignment
The way Alignment works is to first establish a virtual coordinate system in a rectangle, the origin of this virtual coordinate system is the midpoint of the rectangle, and then (x, y) is the positioning point in this virtual coordinate system, and specifies (x , y) represent relative values, for example, Alignment(0.0, 0.0) is the midpoint, and Alignment(1.0, 1.0) is the lower right corner, as shown in the figure:
The unit of the relative value of x in (x, y) is half of the width of the rectangle . For example, 2.0 is equivalent to the width of the entire rectangle; y is similar, and the unit of y is half of the height of the rectangle.
Then, it is converted into the positioning point in the coordinate system with the upper left corner of the rectangle as the origin through a formula. The conversion formula is as follows: (x * w/2 + w/2, y * h/2 + h/2)
, where w is the width of the rectangle and h is the height of the rectangle. Combine the following diagram to understand the calculation process:
The green frame is this rectangle, the black coordinate axis is the virtual coordinate system, and the blue coordinate axis is the target coordinate system with the upper left corner of the rectangle as the origin. Taking the abscissa x on the virtual coordinate axis as an example, the abscissa x' of the converted target point = half the width of the rectangle plus x * half the width of the rectangle (the unit of x in the virtual coordinate axis is half the width of the rectangle).
For example, the abscissa value of Alignment(2.0, 0.0) after conversion is 1.5 times the width of the rectangle, not twice the width of the rectangle.
How Align Works
There is this sentence in Align's official documentation:
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 thechild
such that both points are lined up on top of each other.
That means, first use the description of the alignment property to find a point in the coordinate system of the subcomponent and another point in the coordinate system of the Align component; then Align places the subcomponent in a position where the two points coincide.
wrong interpretation
As can be seen from the above description, the final placement coordinates are also related to the size of Align, because alignment is used to calculate a point in Align in the process. But I only see from the example description of the official documentation that the calculation is related to subcomponents:
And the explanations of some tutorials I saw on the Internet are also wrong, such as this:
To prove this error is simple, place the Align in a Container, set the alignment to Alignment(1.0, 0.0), and place a random child component, like this:
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, ), ), ),
You will find that no matter how you change the width of the outer Container, the right side of the inner red rectangle is always coincident with the right side of the outer Container. How is this done if the coordinates of the positioning are only relative to the width of the child component?
my understanding
In the official document how it works, the principle of calculation has been given, but no specific formula has been given. I looked at the relevant source code and confirmed that there is no problem with the description of how it works. Below I use a simple example to illustrate the calculation process and give the correct calculation formula.
The green rectangle in the above picture is the size of Align, and the red is the sub-component. I still use Alignment(1.0, 0.0) to illustrate. The abscissa of the point described by Alignment(1.0, 0.0) is in the right border of both the green rectangle and the red rectangle. If Align positions the subcomponent according to this position, the red rectangle should be in the red dashed box. But according to the description of how it works, when Align places subcomponents, the two points coincide, that is, the point of the right border of the red rectangle coincides with the point of the right border of the green rectangle. At this time, we only need to move from the position of the red dotted frame to the position of the solid frame, that is: the abscissa of the anchor point in Align minus the abscissa of the anchor point in the subcomponent:
alignWidth / 2 + x * (alignWidth / 2) - childWidth / 2 - x * (childWidth / 2)
The y value of the coordinates can also be described by a similar process, so the calculation formula of the final positioning point should be:
var x = (alignWidth - childWidth) / 2 + x * ((alignWidth - childWidth) / 2); var y = (alignHeight - childHeight) / 2 + x * ((parentHeight - childHeight) / 2);
Finally, a similar process can be used to describe positioning if alignment is FractionalOffset. The difference between FractionalOffset and Alignment is that the origin of FractionalOffset in the virtual coordinate system is in the upper left corner of the rectangle, and the unit of x in FractionalOffset(x, y) is the entire width of the rectangle, not half. Positioning in Align still follows the two FractionalOffset points to keep coincident.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。