Flutter 对齐与相对定位

对齐与相对定位(Align)

定义

1
2
3
4
5
6
Align({
this.alignment = Alignment.center,
this.widthFactor,
this.heightFactor,
Widget child,
})
  • alignment : 需要一个AlignmentGeometry类型的值,表示子组件在父组件中的起始位置。AlignmentGeometry 是一个抽象类,它有两个常用的子类:Alignment和 FractionalOffset,我们将在下面的示例中详细介绍。
  • widthFactor和heightFactor是用于确定Align 组件本身宽高的属性;
    • 它们是两个缩放因子,会分别乘以子元素的宽、高,最终的结果就是Align 组件的宽高。
    • 如果值为null,则组件的宽高将会占用尽可能多的空间。
1
2
3
4
5
6
7
8
9
10
11
12
13
Container(
height: 120.0, // 高度父组件决定
// width: 120.0, // 宽度使用align确定, 优先级大于子组件
color: Colors.blue.shade50,
child: Align(
widthFactor: 3, // 宽度为自身的3倍,
// 当align和父组件都设置了的话,父组件的生效
alignment: Alignment.topRight, // 对齐位置是右上角, 即子组件和父组件的右上角对齐
child: FlutterLogo(
size: 60,
),
),
);

Alignment

定义:Alignment(this.x, this.y)
Alignment继承自AlignmentGeometry,表示矩形内的一个点,他有两个属性x、y,分别表示在水平和垂直方向的偏移
Alignment Widget会以矩形的中心点作为坐标原点,即Alignment(0.0, 0.0) 。x、y的值从-1到1分别代表矩形左边到右边的距离和顶部到底边的距离,因此2个水平(或垂直)单位则等于矩形的宽(或高); 如Alignment(-1.0, -1.0) 代表矩形的左侧顶点

具体偏移为
offset(x, y) = (Alignment.x * childWidth / 2 + childWidth / 2, Alignment.y * childHeight / 2 + childHeight / 2)

1
2
3
4
5
6
7
8
9
10
11
12
13
Container(
height: 120.0, // 高度父组件决定
// width: 120.0, // 宽度使用align确定, 优先级大于子组件
color: Colors.blue.shade50,
child: Align(
widthFactor: 3, // 宽度为自身的3倍,
// 当align和父组件都设置了的话,父组件的生效
alignment: Alignment(2, 0), // 对齐位置为
child: FlutterLogo(
size: 60,
),
),
);

FractionalOffset

FractionalOffset 继承自 Alignment,它和 Alignment唯一的区别就是坐标原点不同!FractionalOffset 的坐标原点为矩形的左侧顶点,这和布局系统的一致,所以理解起来会比较容易。
偏移指的是x y的偏移;

转换公式为:
实际偏移 = (FractionalOffset.x * childWidth, FractionalOffset.y * childHeight)

1
2
3
4
5
Align(
alignment: FractionalOffset(0.5, 1),
child: FlutterLogo(
size: 60,
),

可以看到,Align和Stack/Positioned都可以用于指定子元素相对于父元素的偏移,但它们还是有两个主要区别:

定位参考系统不同;Stack/Positioned定位的的参考系可以是父容器矩形的四个顶点;而Align则需要先通过alignment 参数来确定坐标原点,不同的alignment会对应不同原点,最终的偏移是需要通过alignment的转换公式来计算出。
Stack可以有多个子元素,并且子元素可以堆叠,而Align只能有一个子元素,不存在堆叠。

Center

1
2
3
4
5
Center({
double? widthFactor,
double? heightFactor,
Widget? child
})

可以看到Center继承自Align,它比Align只少了一个alignment 参数;由于Align的构造函数中alignment 值为Alignment.center,所以,我们可以认为Center组件其实是对齐方式确定(Alignment.center)了的Align。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
DecoratedBox(
decoration: BoxDecoration(color: Colors.red),
child: Center(
child: Text("xxx"),
),
),
DecoratedBox(
decoration: BoxDecoration(color: Colors.red),
child: Center(
widthFactor: 1,
heightFactor: 1,
child: Text("xxx"),
),
)

两种偏移类Alignment 和FractionalOffset,区别及各自的坐标转化公式

在需要制定一些精确的偏移时应优先使用FractionalOffset,因为它的坐标原点和布局系统相同,能更容易算出实际偏移。

文章目录
  1. 1. 对齐与相对定位(Align)
    1. 1.0.1. Alignment
    2. 1.0.2. FractionalOffset
    3. 1.0.3. Center