多子布局組件
在開發(fā)中蜀变,我們經(jīng)常需要將多個(gè)Widget放在一起進(jìn)行布局驻售,比如水平方向、垂直方向排列看政,甚至有時(shí)候需要他們進(jìn)行層疊肴盏,比如圖片上面放一段文字等;
這個(gè)時(shí)候我們需要使用多子布局組件(Multi-child layout widgets)帽衙。
比較常用的多子布局組件是Row、Column贞绵、Stack厉萝。
1. Flex組件
Row
組件和Column
組件都繼承自Flex
;
-
Flex
組件和Row
、Column
屬性主要的區(qū)別就是多一個(gè)direction
; - 當(dāng)
direction
的值為Axis.horizontal
的時(shí)候榨崩,則是Row
谴垫,呈一行排布; - 當(dāng)
direction
的值為Axis.vertical
的時(shí)候母蛛,則是Column
翩剪,呈一列排布;
它們都有主軸(Main Axis)和交叉軸(Cross Axis)的概念:
-
對于Row來說彩郊,水平方向是主軸前弯,豎直方向是交叉軸;
Row@2x.png -
對于Column來說秫逝,豎直方向是主軸恕出,水平方向是交叉軸;
Column.png
2. Row組件
Row({
Key key,
MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start, // 主軸對齊方式
MainAxisSize mainAxisSize = MainAxisSize.max, // 水平方向盡可能大
CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center, // 交叉處對齊方式
TextDirection textDirection, // 水平方向子widget的布局順序(默認(rèn)為系統(tǒng)當(dāng)前Locale環(huán)境的文本方向(如中文违帆、英語都是從左往右浙巫,而阿拉伯語是從右往左))
VerticalDirection verticalDirection = VerticalDirection.down, // 表示Row縱軸(垂直)的對齊方向
TextBaseline textBaseline, // 如果上面是baseline對齊方式,那么選擇什么模式(有兩種可選)
List<Widget> children = const <Widget>[],
})
2.1. mainAxisSize
Row的特點(diǎn):
水平方向盡可能占據(jù)較大的空間刷后;
-
垂直方向包裹內(nèi)容;
WechatIMG49.jpeg -
如果水平方向也希望包裹內(nèi)容的畴,那么設(shè)置mainAxisSize = min;
WechatIMG48.jpeg
return RaisedButton(
onPressed: (){
},
color: Colors.red,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.favorite),
Text("收藏"),
],
),
);
2.2. mainAxisAlignment
元素在Row主軸上的布局方式尝胆,它是一個(gè)枚舉類型:
-
start
:主軸開始的位置挨個(gè)擺放元素丧裁; -
end
:主軸結(jié)束的位置挨個(gè)擺放元素; -
center
:主軸的中心點(diǎn)對齊班巩; -
spaceBetween
: 左右兩邊的間距為0渣慕,其他元素之間平分間距嘶炭; -
spaceAround
:左右兩邊的間距是其他元素的間距的一半; -
spaceEvenly
:間距平分逊桦;
class _YZHomeContentState extends State<YZHomeContent> {
@override
Widget build(BuildContext context) {
return Row(
children: [
Container(width: 80, height: 60, color: Colors.red,),
Container(width: 120, height: 100, color: Colors.orange,),
Container(width: 90, height: 80, color: Colors.blue,),
Container(width: 50, height: 50, color: Colors.green,),
],
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
);
}
}
WechatIMG50.jpeg
2.3. CrossAxisAlignment
crossAxisAlignment: CrossAxisAlignment.end,
元素在Row交叉軸上的布局方式
-
start
:交叉軸的起始位置對齊眨猎; -
end
:交叉軸的結(jié)束位置對齊(垂直方向是包裹內(nèi)容的); -
center
:中心點(diǎn)對齊(默認(rèn)值) -
baseLine
:基線對齊强经;(必須有文本才有效果) -
stretch
: 先將Row占據(jù)交叉軸盡可能大的空間睡陪,再將所有的子Widget拉伸到最大;
2.4. Expanded
空間分配:拉伸或收縮匿情;
- 如果控件之間有間隔:拉伸兰迫;
-
如果控件組合寬度超過了屏幕,則壓縮炬称;
WechatIMG943.jpeg
如上圖汁果,間隔等分,如果想把所有間隔分配給第一個(gè)玲躯;
return Row(
children: [
Expanded(
child: Container(width: 80, height: 60, color: Colors.red,),
),
Container(width: 120, height: 100, color: Colors.orange,),
Container(width: 90, height: 80, color: Colors.blue,),
Container(width: 50, height: 50, color: Colors.green,),
],
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.end,
);
}
}
效果:
-
第一個(gè)控件寬度做了拉伸据德;
WechatIMG942.jpeg
2.4.1 flex
作用
Expanded(
flex: 1,
child: Container(width: 80, height: 60, color: Colors.red,),
),
Expanded(
flex: 2,
child: Container(width: 40, height: 60, color: Colors.green,),
),
剩余空間分配比例: 當(dāng)有多個(gè)Expanded
時(shí),
- 如果flex相等跷车,則拉伸的寬度相同棘利;
- 如果flex不等,按比例拉伸朽缴,如上面
flex:2
控件的寬度拉伸為flex: 1
寬度的2倍善玫,原來的width
數(shù)值不再起作用。
3. Column組件
同Row;
4. Stack組件
在開發(fā)中密强,我們多個(gè)組件很有可能需要重疊顯示茅郎,比如在一張圖片上顯示文字或者一個(gè)按鈕等。在Flutter中我們需要使用層疊布局Stack誓斥。
4.1 Stack介紹
Stack的大小默認(rèn)是包裹內(nèi)容的.
- alignment:從什么位置開始排布所有的子Widget;
- fit: expand 將子元素拉伸到盡可能大;
- overflow:超出部分如何處理;
Stack({
Key key,
this.alignment = AlignmentDirectional.topStart,
this.textDirection,
this.fit = StackFit.loose,
this.overflow = Overflow.clip,
this.clipBehavior = Clip.hardEdge,
List<Widget> children = const <Widget>[],
})
4.2 示例
class _YZHomeContentState extends State<YZHomeContent> {
@override
Widget build(BuildContext context) {
return Stack(
alignment: AlignmentDirectional.bottomCenter,
overflow: Overflow.visible,
children: [
Image.asset("assets/images/image_01.png",),
Container(width: 150, height: 50, color: Colors.red,),
// Positioned( //文字在Stack內(nèi)部相對布局調(diào)整
// right: 10,
// bottom: 20,
// child:
Text("這是圖片上的文字"),
// ),
],
);
}
}
WechatIMG51.jpeg
class _YZHomeContentState extends State<YZHomeContent> {
bool _isFavor = false;
@override
Widget build(BuildContext context) {
return Stack(
children: [
Image.asset("assets/images/image_02.jpeg",width: MediaQuery.of(context).size.width,),
Positioned(
left: 0,
right: 0,
bottom: 0,
child: Container(
padding: EdgeInsets.all(8),
color: Color.fromARGB(10, 0, 0, 0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text("這是圖片上的文字描述", style: TextStyle(fontSize: 15, color: Colors.red),),
IconButton(
icon: Icon(
Icons.favorite,
color: _isFavor ? Colors.red : Colors.white,
),
onPressed: () {
setState(() {
_isFavor = !_isFavor;
});
}),
],
),
),
),
],
);
}
}
WechatIMG52.jpeg