咱们讲过经过StackPositioned,咱们能够指定一个或多个子元素相对于父元素各个边的准确偏移,而且能够重叠。但假如咱们只想简略的调整一个子元素在父元素中的方位的话,运用Align组件会更简略一些。

Align

Align 组件能够调整子组件的方位,界说如下:

Align({
  Key key,
  this.alignment = Alignment.center,
  this.widthFactor,
  this.heightFactor,
  Widget child,
})
  • alignment : 需求一个AlignmentGeometry类型的值,表明子组件在父组件中的起始方位。AlignmentGeometry 是一个抽象类,它有两个常用的子类:Alignment和 FractionalOffset,咱们将在下面的示例中具体介绍。
  • widthFactor和heightFactor是用于确认Align 组件本身宽高的属性;它们是两个缩放因子,会别离乘以子元素的宽、高,终究的结果便是Align 组件的宽高。假如值为null,则组件的宽高将会占用尽可能多的空间。

咱们先来看一个简略的比如:

Container(
  height: 120.0,
  width: 120.0,
  color: Colors.shade50,
  child: Align(
    alignment: Alignment.topRight,
    child: FlutterLogo(
      size: 60,
    ),
  ),
)

运转作用:

40、Flutter之widgets 组件布局对齐与相对定位(Align)
FlutterLogo 是Flutter SDK 供给的一个组件,内容便是 Flutter 的 logo 。在上面的比如中,咱们显式指定了Container的宽、高都为 120。假如咱们不显式指定宽高,而经过一起指定widthFactor和heightFactor 为 2 也是能够达到同样的作用:

Align(
  widthFactor: 2,
  heightFactor: 2,
  alignment: Alignment.topRight,
  child: FlutterLogo(
    size: 60,
  ),
),

由于FlutterLogo的宽高为 60,则Align的终究宽高都为2*60=120

另外,咱们经过Alignment.topRightFlutterLogo定位Container的右上角。那Alignment.topRight是什么呢?经过源码咱们能够看到其界说如下:

//右上角
static const Alignment topRight = Alignment(1.0, -1.0);

能够看到它仅仅Alignment的一个实例,下面咱们介绍一下Alignment

Alignment

Alignment承继自AlignmentGeometry,表明矩形内的一个点,他有两个属性xy,别离表明在水平缓笔直方向的偏移,Alignment界说如下:

Alignment(this.x, this.y)

Alignment Widget会以矩形的中心点作为坐标原点,即Alignment(0.0, 0.0) 。x、y的值从-1到1别离代表矩形左面到右边的间隔和顶部到底边的间隔,因此2个水平(或笔直)单位则等于矩形的宽(或高),如Alignment(-1.0, -1.0) 代表矩形的左侧极点,而Alignment(1.0, 1.0)代表右侧底部终点,而Alignment(1.0, -1.0) 则正是右侧极点,即Alignment.topRight。为了运用方便,矩形的原点、四个极点,以及四条边的终点在Alignment类中都已经界说为了静态常量。

Alignment能够经过其坐标转化公式将其坐标转为子元素的具体偏移坐标:

(Alignment.x*childWidth/2+childWidth/2, Alignment.y*childHeight/2+childHeight/2)

其间childWidth为子元素的宽度,childHeight为子元素高度。

现在咱们再看看上面的示例,咱们将Alignment(1.0, -1.0)带入上面公式,可得FlutterLogo的实践偏移坐标正是(60,0)。下面再看一个比如:

 Container(
  color: Colors.blue.shade100,
  child: const Align(
  widthFactor: 2,
  heightFactor: 2,
  alignment: Alignment(2.0,0),
  child: FlutterLogo(size: 60,),
),)

咱们能够先想象一下运转作用:将Alignment(2,0.0)带入上述坐标转化公式,能够得到FlutterLogo的实践偏移坐标为(90,30)。

40、Flutter之widgets 组件布局对齐与相对定位(Align)

FractionalOffset

FractionalOffset 承继自 Alignment,它和 Alignment唯一的差异便是坐标原点不同!FractionalOffset 的坐标原点为矩形的左侧极点,这和布局体系的一致,所以了解起来会比较简单。FractionalOffset的坐标转化公式为:

实践偏移 = (FractionalOffse.x * childWidth, FractionalOffse.y * childHeight)

比如:

Container(
  height: 120,
  width: 120,
  color: Colors.blue[100],
  child: const Align(alignment: FractionalOffset(0.2,0.9),
    child: FlutterLogo(size: 60,),
  ),
)

实践运转作用如图

40、Flutter之widgets 组件布局对齐与相对定位(Align)

咱们将FractionalOffset(0.2, 0.9)带入坐标转化公式得FlutterLogo实践偏移为(12,54),和实践运转作用符合。

Align和Stack对比

能够看到,Align和Stack/Positioned都能够用于指定子元素相对于父元素的偏移,但它们仍是有两个主要差异:

  1. 定位参考体系不同;Stack/Positioned定位的的参考系能够是父容器矩形的四个极点;而Align则需求先经过alignment 参数来确认坐标原点,不同的alignment会对应不同原点,终究的偏移是需求经过alignment的转化公式来计算出。
  2. Stack能够有多个子元素,而且子元素能够堆叠,而Align只能有一个子元素,不存在堆叠。

Center组件

Center为居中定位元素组件。经过查找SDK源码,咱们看到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,它比Align只少了一个alignment 参数;由于Align的结构函数中alignment 值为Alignment.center,所以,咱们能够认为Center组件其实是对齐方法确认(Alignment.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"),
  ),
)

运转作用:

40、Flutter之widgets 组件布局对齐与相对定位(Align)

总结

Align组件及两种偏移类AlignmentFractionalOffset,需求了解这两种偏移类的差异及各自的坐标转化公式。另外,在此主张读者在需求制定一些准确的偏移时应优先运用FractionalOffset,由于它的坐标原点和布局体系相同,能更简单算出实践偏移。

还有,熟悉Web开发的同学可能会发现Align组件的特性和Web开发中相对定位(position: relative)十分像,是的!在大多数时候,咱们能够直接运用Align组件来完成Web中相对定位的作用。

完好demo源码:flutter_demo: flutter组件测试学习demo

本文正在参与「金石计划 . 瓜分6万现金大奖」