層疊布局
層疊布局和Web中的絕對定位、Android中的Frame布局是相似的葵陵,子widget可以根據(jù)到父容器四個角的位置來確定本身的位置液荸。絕對定位允許子widget堆疊(按照代碼中聲明的順序)。Flutter中使用Stack和Positioned來實現(xiàn)絕對定位脱篙,Stack允許子widget堆疊娇钱,而Positioned可以給子widget定位(根據(jù)Stack的四個角)。
Stack
Stack({
this.alignment = AlignmentDirectional.topStart,
this.textDirection,
this.fit = StackFit.loose,
this.overflow = Overflow.clip,
List<Widget> children = const <Widget>[],
})
- alignment:此參數(shù)決定如何去對齊沒有定位(沒有使用Positioned)或部分定位的子widget绊困。所謂部分定位文搂,在這里特指沒有在某一個軸上定位:left、right為橫軸秤朗,top煤蹭、bottom為縱軸,只要包含某個軸上的一個定位屬性就算在該軸上有定位取视。
- textDirection:和Row硝皂、Wrap的textDirection功能一樣,都用于決定alignment對齊的參考系即:textDirection的值為TextDirection.ltr作谭,則alignment的start代表左稽物,end代表右;textDirection的值為TextDirection.rtl折欠,則alignment的start代表右贝或,end代表左。
- fit:此參數(shù)用于決定沒有定位的子widget如何去適應Stack的大小锐秦。StackFit.loose表示使用子widget的大小咪奖,StackFit.expand表示擴伸到Stack的大小。
- overflow:此屬性決定如何顯示超出Stack顯示空間的子widget酱床,值為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用于指定定位元素的寬度和高度,注意楞慈,此處的width幔烛、height 和其它地方的意義稍微有點區(qū)別,此處用于配合left囊蓝、top 饿悬、right、 bottom來定位widget聚霜,舉個例子狡恬,在水平方向時,你只能指定left蝎宇、right弟劲、width三個屬性中的兩個,如指定left和width后姥芥,right會自動算出(left+width)兔乞,如果同時指定三個屬性則會報錯,垂直方向同理凉唐。
示例
class _home extends StatefulWidget{
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return _homeState();
}
}
class _homeState extends State<_home>{
@override
Widget build(BuildContext context) {
// TODO: implement build
return new Scaffold(
appBar: new AppBar(
title: new Text("title"),
centerTitle: true,
),
body: //通過ConstrainedBox來確保Stack占滿屏幕
ConstrainedBox(
constraints: BoxConstraints.expand(),
child: Stack(
alignment:Alignment.center , //指定未定位或部分定位widget的對齊方式
children: <Widget>[
Container(child: Text("Hello world",style: TextStyle(color: Colors.white)),
color: Colors.red,
),
Positioned(
left: 18.0,
child: Text("I am Jack"),
),
Positioned(
top: 18.0,
child: Text("Your friend"),
)
],
),
)
);
}
}
由于第一個子widget Text("Hello world")沒有指定定位庸追,并且alignment值為Alignment.center,所以台囱,它會居中顯示淡溯。第二個子widget Text("I am Jack")只指定了水平方向的定位(left),所以屬于部分定位玄坦,即垂直方向上沒有定位血筑,那么它在垂直方向?qū)R方式則會按照alignment指定的對齊方式對齊,即垂直方向居中煎楣。對于第三個子widget Text("Your friend")豺总,和第二個Text原理一樣,只不過是水平方向沒有定位择懂,則水平方向居中喻喳。
我們給上例中的Stack指定一個fit屬性,然后將三個子widget的順序調(diào)整一下:
class _home extends StatefulWidget{
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return _homeState();
}
}
class _homeState extends State<_home>{
@override
Widget build(BuildContext context) {
// TODO: implement build
return new Scaffold(
appBar: new AppBar(
title: new Text("title"),
centerTitle: true,
),
body: //通過ConstrainedBox來確保Stack占滿屏幕
Stack(
alignment:Alignment.center ,
fit: StackFit.expand, //未定位widget占滿Stack整個空間
children: <Widget>[
Positioned(
left: 18.0,
child: Text("I am Jack"),
),
Container(child: Text("Hello world",style: TextStyle(color: Colors.white)),
color: Colors.red,
),
Positioned(
top: 18.0,
child: Text("Your friend"),
)
],
),
);
}
}