介紹
層疊布局和Web中的絕對定位、Android中的Frame布局是相似的,子組件可以根據(jù)距父容器四個角的位置來確定自身的位置。絕對定位允許子組件堆疊起來(按照代碼中聲明的順序)。Flutter中使用Stack和Positioned這兩個組件來配合實現(xiàn)絕對定位。Stack允許子組件堆疊,而Positioned用于根據(jù)Stack的四個角來確定子組件的位置。
先簡單使用下Stack
import 'package:flutter/material.dart';
main(List<String> args) {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "demo",
home: Scaffold(
appBar: AppBar(title: Text("bar")),
body: HomeContent(),
),
);
}
}
class HomeContent extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(child: Stack(
children: [
Container(
height: 300,
width: 300,
color: Colors.blue[200],
),
Text("一段文字")
],
));
}
}
可以發(fā)現(xiàn),正常情況下,當Text和Container組件并排時,文字會出現(xiàn)在盒子的后面,但是使用了stack后,文字與盒子出現(xiàn)在同一區(qū)域(其實是文字在盒子上面)。

image.png
參數(shù)列表
Stack({
this.alignment = AlignmentDirectional.topStart,
this.textDirection,
this.fit = StackFit.loose,
this.overflow = Overflow.clip,
List<Widget> children = const <Widget>[],
})
-
alignment:此參數(shù)決定如何去對齊沒有定位(沒有使用Positioned)或部分定位的子組件。所謂部分定位,在這里特指沒有在某一個軸上定位:left、right為橫軸,top、bottom為縱軸,只要包含某個軸上的一個定位屬性就算在該軸上有定位。 -
textDirection:和Row、Wrap的textDirection功能一樣,都用于確定alignment對齊的參考系,即:textDirection的值為TextDirection.ltr,則alignment的start代表左,end代表右,即從左往右的順序;textDirection的值為TextDirection.rtl,則alignment的start代表右,end代表左,即從右往左的順序。 -
fit:此參數(shù)用于確定沒有定位的子組件如何去適應Stack的大小。StackFit.loose表示使用子組件的大小,StackFit.expand表示擴伸到Stack的大小。 -
overflow:此屬性決定如何顯示超出Stack顯示空間的子組件;值為Overflow.clip時,超出部分會被剪裁(隱藏),值為Overflow.visible時則不會。
Positioned
const Positioned({
Key key,
this.left,
this.top,
this.right,
this.bottom,
this.width,
this.height,
@required Widget child,
})
left、top 、right、 bottom分別代表離Stack左、上、右、底四邊的距離。width和height用于指定需要定位元素的寬度和高度。注意,Positioned的width、height 和其它地方的意義稍微有點區(qū)別,此處用于配合left、top 、right、 bottom來定位組件,舉個例子,在水平方向時,你只能指定left、right、width三個屬性中的兩個,如指定left和width后,right會自動算出(left+width),如果同時指定三個屬性則會報錯,垂直方向同理。
import 'package:flutter/material.dart';
main(List<String> args) {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "demo",
home: Scaffold(
appBar: AppBar(title: Text("bar")),
body: HomeContent(),
),
);
}
}
class HomeContent extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(child: Container(
width: 300,
height: 300,
color: Colors.blue[200],
child: Stack(
children: <Widget>[
Positioned(
left: 0,
top: 0,
child: Icon(Icons.home),
),
Positioned(
right: 0,
bottom: 0,
child: Icon(Icons.home),
),
Positioned(
left: 150,
top: 150,
child: Icon(Icons.home),
)
],
),
));
}
}

image.png
注意要考慮元素自身的大小
Align
參數(shù)列表
Align({
Key key,
this.alignment = Alignment.center,
this.widthFactor,
this.heightFactor,
Widget child,
})
-
alignment: 需要一個AlignmentGeometry類型的值,表示子組件在父組件中的起始位置。AlignmentGeometry是一個抽象類,它有兩個常用的子類:Alignment和FractionalOffset,我們將在下面的示例中詳細介紹。 -
widthFactor和heightFactor是用于確定Align組件本身寬高的屬性;它們是兩個縮放因子,會分別乘以子元素的寬、高,最終的結果就是Align組件的寬高。如果值為null,則組件的寬高將會占用盡可能多的空間。
import 'package:flutter/material.dart';
main(List<String> args) {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "demo",
home: Scaffold(
appBar: AppBar(title: Text("bar")),
body: HomeContent(),
),
);
}
}
class HomeContent extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(child: Container(
width: 300,
height: 300,
color: Colors.blue[200],
child: Stack(
children: <Widget>[
Align(
alignment: Alignment(1, 1),
child: Icon(Icons.home),
),
Align(
alignment: Alignment(0, 0),
child: Icon(Icons.home),
),
Align(
alignment: Alignment(-1, -1),
child: Icon(Icons.home),
)
],
),
));
}
}

image.png