文章已同步至掘金: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"),
),
)
],
),
);
运行效果:
评论区