iOS-Flutter 对齐与相对定位

33 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 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"),
  ),
)