开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 19 天,点击查看活动详情
了解Stack和Positioned,我们可以指定一个或多个子元素对于父元素各个边的精确偏移,并且可以重叠,但是如果我们只是简单的调整一个子元素在父元素中的位置的话,使用Align组件会更简单一些。
Align
Align({
Key key,
this.alignment = Alignment.center,//对齐方式,需要一个AlignmentGeometry类型的值,表示子组件在父组件的起始位置。AlignmentGeometry是一个抽象类,常用的两个子类(Alignment和FractionalOffset)继承于AlignmentGeometry。
this.widthFactor,用于确定组件本书的宽高属性,它们是两个缩放因子,会分别乘以字元素的宽高,最终结果就是Align组件的宽高,如果值为bull,会占用尽可能多的空间。
this.heightFactor,
Widget child,
})
实例:
Container(
height: 120.0,
width: 120.0,
color: Colors.blue.shade50,
child: Align(
widthFactor: 2,//宽放大2倍
heightFactor: 2,//高放大2倍
alignment: Alignment.topRight,//右上角对齐
child: FlutterLogo(
size: 60,
),
),
)
Alignment
Alignment 继承自AlignmentGeometry表示矩形内的一个点,有两个属性x、y分别表示在水平和垂直方向的偏移。Widget会以矩形的中心点作为坐标原点,即Alignment(0,0),x、y的值从-1到1分别代表矩形左边到右边的距离和顶部到底边的距离,因此2个水平(或垂直)单位则等于矩形的宽或高,如Aliginmen(-1,-1)代表矩形的左顶点,为了方便使用,矩形的原点、四个顶点,以及四条边的终点在Alignment类中都已经定义为静态常量。 Alignment可以通过其坐标转换公式,将坐标转换为子元素的具体偏移坐标。
childWidth 为子元素的宽度,childHeight为子元素的高度
(Alignment.x*childWidth/2+childWidth/2, Alignment.y*childHeight/2+childHeight/2)
FractionalOffset
FractionalOffset继承自Alignment,区别是坐标原点不同,FractionalOffset的坐标原点为矩形的左侧顶点,和布局系统一致。转换公式为:
实际偏移 = (FractionalOffse.x * childWidth, FractionalOffse.y * childHeight)
举例:
Container(
height: 120.0,
width: 120.0,
color: Colors.blue[50],
child: Align(
alignment: FractionalOffset(0.2, 0.6),
child: FlutterLogo(
size: 60,
),
),
)
//计算FractionalOffset(0.2,0.6),带入换算公式计算实际偏移为:(12,36)。
Align和Stack对比
Align和Stack/Positioned都可以用于指定子元素相对于父元素的偏移,但是区别是:
- 定位参考系统不同,Stack/Positioned参考系是父容器的四个顶点,而Aligin则需要先通过Alignment参数来确定坐标原点,不同的alignment会对应不同的原点,最终的偏移是需要通过alignment的转换公式计算出来的。
- Stack可以有多个元素,并且可以多元素堆叠,Align只能有一个元素。
Center
class Center extends Align {
const Center({ Key? key, double widthFactor, double heightFactor, Widget? child })
: super(key: key, widthFactor: widthFactor, heightFactor: heightFactor, child: child);
}
可以看到Center继承自Align,里面的大多属性也介绍过。需要注意的是widthFactor和heightFactor为null时,组件的宽高将会占用尽可能多的空间。
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"),
),
)