文章已同步至掘金:https://juejin.cn/post/6844903957051998222
欢迎访问😃,有任何问题都可留言评论哦~
在Flutter中,如果想指定组件的位置的话,可以使用Stack和Positioned,他们可以指定一个或多个子元素相对于父元素各个边的精确偏移,并且可以重叠。
但是如果我们只想简单的调整一个子元素在父元素中的位置的话,使用Align组件会更简单一些。
我们也可以使用Center组件,让子元素都居中显示
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: 200.0,
width: 200.0,
color: Colors.blue[50],
child: Align(
alignment: Alignment.topRight,
child: Image(
width: 100,
height: 100,
image: AssetImage('images/Test.jpg'),
)),
);
运行效果:

在这个例子中,我们指定了Container的宽高都为200,
如果我们不显式指定宽高,而通过同时指定widthFactor和heightFactor为 2 也是可以达到同样的效果:
Container(
// height: 200.0,
// width: 200.0,
color: Colors.blue[50],
child: Align(
widthFactor: 2,
heightFactor: 2,
alignment: Alignment.topRight,
child: Image(
width: 100,
height: 100,
image: AssetImage('images/Test.jpg'),
)),
);
因为这个图片的宽高都是 100,则Align的最终宽高就是 100*2=200
Alignment
在上面的例子中,我们指定了图片的位置alignment: Alignment.topRight, 意思就是显示在右上角,当然还有其他的值,例如:
- topLeft 左上角
- topRight 右上角
- topCenter 上中
- center 中心
- centerLeft 左中
- centerRight 右中
- bottomLeft 左下角
- bottomCenter 下中
- bottomRight 右下角
当然,我们也可以用坐标的形式表示,Alignment继承自AlignmentGeometry,表示矩形内的一个点,他有两个属性x、y,分别表示在水平和垂直方向的偏移量。
定义:Alignment(this.x, this.y)
坐标转换公式:(Alignment.x*childWidth/2+childWidth/2, Alignment.x*childHeight+childHeight/2)
其中childWidth为子元素的宽度,childHeight为子元素高度。
但是他比较特殊,他的坐标原点,是矩形的中心点,而不是我们Web中的左上角的那个点,
如果你这样写:Alignment(-1, -1),那他表示的就是左上角的那个点,一定要注意。
代码示例:
Container(
color: Colors.blue[50],
child: Align(
widthFactor: 2,
heightFactor: 2,
alignment: Alignment(0,0),
child: Image(
width: 100,
height: 100,
image: AssetImage('images/Test.jpg'),
)),
);
运行效果:

Container(
color: Colors.blue[50],
child: Align(
widthFactor: 2,
heightFactor: 2,
alignment: Alignment(2,0),
child: Image(
width: 100,
height: 100,
image: AssetImage('images/Test.jpg'),
)),
);
运行效果:

FractionalOffset
上面我们说了,Alignment的坐标原点是中心点,而FractionalOffset就不一样了,FractionalOffset继承自 Alignment,它和Alignment唯一的区别就是坐标原点不同。
坐标转换公式:实际偏移 = (FractionalOffse.x * childWidth, FractionalOffse.y * childHeight)
他的坐标原点为矩形的左上角,这和Web是一样的
代码示例:
Container(
color: Colors.blue[50],
child: Align(
widthFactor: 2,
heightFactor: 2,
alignment: FractionalOffset(0,0),
child: Image(
width: 100,
height: 100,
image: AssetImage('images/Test.jpg'),
)),
);
运行效果:

Align和Stack对比
可以看到,Align和Stack/Positioned都可以用于指定子元素相对于父元素的偏移,但它们还是有两个主要区别:
-
定位参考系统不同;
Stack/Positioned定位的的参考系可以是父容器矩形的四个顶点;而Align则需要先通过alignment参数来确定坐标原点,不同的alignment会对应不同原点,最终的偏移是需要通过alignment的转换公式来计算出。 -
Stack可以有多个子元素,并且子元素可以堆叠,而Align只能有一个子元素,不存在堆叠。
Center
这个组件就比较简单了,他可以让他里面的子元素全部居中排列
源码示例
构造函数如下:
class Center extends Align {
/// Creates a widget that centers its child.
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。
代码示例:
Container(
color: Colors.blue[50],
child: Center(
child: Text('xxx'),
)
);
运行效果:

还有一点忘说了,上面说过,当widthFactor或heightFactor为null时组件的宽高将会占用尽可能多的空间,这一点需要特别注意,
代码示例:
Container(
child: Column(
children: <Widget>[
DecoratedBox(
decoration: BoxDecoration(color: Colors.red),
child: Center(
child: Text("xxx"),
),
),
SizedBox(
height: 20,
),
DecoratedBox(
decoration: BoxDecoration(color: Colors.red),
child: Center(
widthFactor: 1,
heightFactor: 1,
child: Text("xxx"),
),
)
],
),
);
运行效果:

评论区