Flutter實(shí)戰(zhàn) 層疊布局 Stack、Positioned

2021-03-08 10:02 更新

層疊布局和 Web 中的絕對(duì)定位、Android 中的 Frame 布局是相似的,子組件可以根據(jù)距父容器四個(gè)角的位置來(lái)確定自身的位置。絕對(duì)定位允許子組件堆疊起來(lái)(按照代碼中聲明的順序)。Flutter 中使用StackPositioned這兩個(gè)組件來(lái)配合實(shí)現(xiàn)絕對(duì)定位。Stack允許子組件堆疊,而Positioned用于根據(jù)Stack的四個(gè)角來(lái)確定子組件的位置。

#Stack

Stack({
  this.alignment = AlignmentDirectional.topStart,
  this.textDirection,
  this.fit = StackFit.loose,
  this.overflow = Overflow.clip,
  List<Widget> children = const <Widget>[],
})

  • alignment:此參數(shù)決定如何去對(duì)齊沒(méi)有定位(沒(méi)有使用Positioned)或部分定位的子組件。所謂部分定位,在這里特指沒(méi)有在某一個(gè)軸上定位:left、right為橫軸,top、bottom為縱軸,只要包含某個(gè)軸上的一個(gè)定位屬性就算在該軸上有定位。
  • textDirection:和Row、WraptextDirection功能一樣,都用于確定alignment對(duì)齊的參考系,即:textDirection的值為TextDirection.ltr,則alignmentstart代表左,end代表右,即從左往右的順序;textDirection的值為TextDirection.rtl,則alignment的start代表右,end代表左,即從右往左的順序。
  • fit:此參數(shù)用于確定沒(méi)有定位的子組件如何去適應(yīng)Stack的大小。StackFit.loose表示使用子組件的大小,StackFit.expand表示擴(kuò)伸到Stack的大小。
  • overflow:此屬性決定如何顯示超出Stack顯示空間的子組件;值為Overflow.clip時(shí),超出部分會(huì)被剪裁(隱藏),值為Overflow.visible 時(shí)則不會(huì)。

#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左、上、右、底四邊的距離。widthheight用于指定需要定位元素的寬度和高度。注意,Positionedwidth、height 和其它地方的意義稍微有點(diǎn)區(qū)別,此處用于配合left、top 、rightbottom來(lái)定位組件,舉個(gè)例子,在水平方向時(shí),你只能指定left、rightwidth三個(gè)屬性中的兩個(gè),如指定leftwidth后,right會(huì)自動(dòng)算出(left+width),如果同時(shí)指定三個(gè)屬性則會(huì)報(bào)錯(cuò),垂直方向同理。

#示例

在下面的例子中,我們通過(guò)對(duì)幾個(gè)Text組件的定位來(lái)演示StackPositioned的特性:

//通過(guò)ConstrainedBox來(lái)確保Stack占滿屏幕
ConstrainedBox(
  constraints: BoxConstraints.expand(),
  child: Stack(
    alignment:Alignment.center , //指定未定位或部分定位widget的對(duì)齊方式
    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"),
      )        
    ],
  ),
);

運(yùn)行效果見(jiàn)圖4-9:

圖4-9

由于第一個(gè)子文本組件Text("Hello world")沒(méi)有指定定位,并且alignment值為Alignment.center,所以它會(huì)居中顯示。第二個(gè)子文本組件Text("I am Jack")只指定了水平方向的定位(left),所以屬于部分定位,即垂直方向上沒(méi)有定位,那么它在垂直方向的對(duì)齊方式則會(huì)按照alignment指定的對(duì)齊方式對(duì)齊,即垂直方向居中。對(duì)于第三個(gè)子文本組件Text("Your friend"),和第二個(gè)Text原理一樣,只不過(guò)是水平方向沒(méi)有定位,則水平方向居中。

我們給上例中的Stack指定一個(gè)fit屬性,然后將三個(gè)子文本組件的順序調(diào)整一下:

Stack(
  alignment:Alignment.center ,
  fit: StackFit.expand, //未定位widget占滿Stack整個(gè)空間
  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"),
    )
  ],
),

顯示效果如圖4-10所示:

圖4-10

可以看到,由于第二個(gè)子文本組件沒(méi)有定位,所以fit屬性會(huì)對(duì)它起作用,就會(huì)占滿Stack。由于Stack子元素是堆疊的,所以第一個(gè)子文本組件被第二個(gè)遮住了,而第三個(gè)在最上層,所以可以正常顯示。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)