層疊布局 Stack、Positioned

介紹

層疊布局和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為橫軸,topbottom為縱軸,只要包含某個軸上的一個定位屬性就算在該軸上有定位。
  • textDirection:和RowWraptextDirection功能一樣,都用于確定alignment對齊的參考系,即:textDirection的值為TextDirection.ltr,則alignmentstart代表左,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 是一個抽象類,它有兩個常用的子類:AlignmentFractionalOffset,我們將在下面的示例中詳細介紹。
  • widthFactorheightFactor是用于確定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
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容