Web 開發者如何理解 Flutter 佈局之 —— 2. Container

弘樹 發表於 2019-10-15

容器元件。

  • 通過盒約束(BoxConstraints)可定義表現(行級/塊級)

  • 通過邊界嵌入(EdgeInsets)可定義邊距(內邊距[padding]/外邊距[margin])

  • 通過裝飾(BoxDecoration)可定義邊框、投影、漸變等

  • 通過對齊(Alignment)可設定對齊方式

1、約束

1.1、無約束

類似於行級元素,跟隨內容的增大而增大。

new Container(
  child: Text("A convenience widget that combines common painting, positioning, and sizing widgets."),
)
複製程式碼

等效於:

<span>
  A convenience widget that combines common painting, positioning, and sizing widgets.
</span>
複製程式碼

1.2、約束最大尺寸

new Container(
  child: Text("A container first surrounds the child with padding (inflated by any borders present in the decoration) and then applies additional constraints to the padded extent (incorporating the width and height as constraints, if either is non-null). The container is then surrounded by additional empty space described from the margin."),
  constraints: BoxConstraints(
    maxWidth: 200,
    maxHeight: 200
  )
)
複製程式碼

等效於:

<div
  style=
  "
    max-width: 200px;
    max-height: 200px;
  "
>
A container first surrounds the child with padding (inflated by any borders present in the decoration) and then applies additional constraints to the padded extent (incorporating the width and height as constraints, if either is non-null). The container is then surrounded by additional empty space described from the margin.
</div>
複製程式碼

1.3、約束最小尺寸

new Container(
  child: Text("Hello Flutter!"),
  constraints: BoxConstraints(
    minWidth: 200,
    minHeight: 200
  )
)
複製程式碼

等效於:

<div
  style=
  "
    min-width: 200px;
    min-height: 200px;
  "
>
  Hello Flutter!
</div>
複製程式碼

1.4、擴充套件至父級元素尺寸

new Container(
  child: Text("Hello Flutter!"),
  constraints: BoxConstraints.expand()
)
複製程式碼

等效於:

<div
  style=
  "
    width: 100%;
    height: 100%;
  "
>
  Hello Flutter!
</div>
複製程式碼

1.5、設定固定尺寸

new Container(
  child: Text("Hello Flutter!"),
  constraints: BoxConstraints.expand(
    width: 200,
    height: 200
  )
)
複製程式碼

等效於:

<div
  style=
  "
    width: 200px;
    height: 200px;
  "
>
  Hello Flutter!
</div>
複製程式碼

2、邊距

2.1、單獨設定

需要單獨設定某方向邊距時,可以使用EdgeInsets.only()

new Container(
  child: Text("Hello Flutter!"),
  padding: EdgeInsets.only(
    top: 10,
    left: 5
  )
)
複製程式碼

等效於:

<div
  style=
  "
    padding-top: 10px;
    padding-left: 5px;
  "
>
  Hello Flutter!
</div>
複製程式碼

2.2、全部設定

所有方向邊距統一時,可以使用 EdgeInsets.all()

new Container(
  child: Text("Hello Flutter!"),
  padding: EdgeInsets.all(10)
)
複製程式碼

等效於:

<div
  style=
  "padding: 10px;"
>
  Hello Flutter!
</div>
複製程式碼

2.3、對稱設定

只需要設定單獨方向,可以使用 EdgeInsets.symmetric()

new Container(
  child: Text("Hello Flutter!"),
  padding: EdgeInsets.symmetric(
    vertical: 10,
	horizontal: 15
  )
)
複製程式碼

等效於:

<div
  style=
  "padding: 10px 15px 10px 15px;"
>
  Hello Flutter!
</div>
複製程式碼

2.4、分別快速設定

縮寫宣告,可以使用 EdgeInsets.fromLTRB(l, t, r, b)

new Container(
  child: Text("Hello Flutter!"),
  padding: EdgeInsets.fromLTRB(5, 10, 15, 20)
)
複製程式碼

等效於:

<div
  style=
  "
    padding-left: 5px;
    padding-top: 10px;
    padding-right: 15px;
    padding-bottom: 20px;
  "
>
  Hello Flutter!
</div>
複製程式碼

3、裝飾

3.0、【這裡有坑】

裝飾屬性存在時,背景色應寫在BoxDecoration中,若BoxDecoration與外層的樣式屬性衝突,則會報錯。

報錯指出,container的 color 是其 BoxDecoration.color 的快捷方式,無法同時存在。

具體情況請參見下面的示例:

new Container(
  child: Text("Hello Flutter!"),
  //此時,由於存在 BoxDecoration, 此處 color 會報錯
  color: Colors.deepPurple,
  decoration: BoxDecoration(
    color: Colors.deepPurple
  )
)
複製程式碼

錯誤詳細資訊:

Cannot provide both a color and a decoration The color argument is just a shorthand for "decoration: new BoxDecoration(color: color)".


3.1、設定邊框

new Container(
  child: Text("Hello Flutter!"),
  decoration: BoxDecoration(
    border: Border.all(
      width: 2,
      style: BorderStyle.solid,
      color: Color(0xff000000)
    )
  )
)
複製程式碼

等效於:

<div
  style=
  "border: 2px solid #000000ff;"
>
  Hello Flutter!
</div>
複製程式碼

3.2、設定投影

new Container(
  child: Text("Hello Flutter!"),
  constraints: BoxConstraints.expand(
    width: 200,
    height: 200
  ),
  decoration: BoxDecoration(
    //此處與webview有差異:若不設定背景色,視為容器透明,此時容器中央以投影顏色顯示並向邊界徑向發散
    color: Colors.white,
    boxShadow: [
      BoxShadow(
        color: Color(0xFFFF0000),
        offset: Offset(5, 10),
        blurRadius: 15
      )
    ]
  )
)
複製程式碼

等效於:

<div
  style=
  "
    width: 200px;
    height: 200px;
    box-shadow: 5px 10px 15px #FF0000FF;
  "
>
  Hello Flutter!
</div>
複製程式碼

3.3、設定漸變

3.3.1、預設線性漸變

new Container(
  child: Text("Hello Flutter!"),
  constraints: BoxConstraints.expand(
    width: 200,
    height: 200
  ),
  decoration: BoxDecoration(
    gradient: LinearGradient(
      colors: [
        Color(0xFF6A11CB),
        Color(0xFF2575FC)
      ]
    )
  )
)
複製程式碼

等效於:

<div
  style=
  "
    width: 200px;
    height: 200px;
    background-image: linear-gradient(to right, #6A11CBFF, #2575FCFF);
  "
>
  Hello Flutter!
</div>
複製程式碼

3.3.1、設定漸變方位

new Container(
  child: Text("Hello Flutter!"),
  constraints: BoxConstraints.expand(
    width: 200,
    height: 200
  ),
  decoration: BoxDecoration(
    gradient: LinearGradient(
      colors: [
        Color(0xFF6A11CB),
        Color(0xFF2575FC)
      ],
      begin: Alignment.topCenter,
      end: Alignment.bottomCenter
    )
  )
)
複製程式碼

等效於:

<div
   style=
   "
      width: 200px;
      height: 200px;
      background-image: linear-gradient(to bottom, #6A11CBFF, #2575FCFF);
   "
>
  Hello Flutter!
</div>
複製程式碼

3.3.1、徑向漸變

new Container(
  child: Text("Hello Flutter!"),
  constraints: BoxConstraints.expand(
    width: 200,
    height: 200
  ),
  decoration: BoxDecoration(
    gradient: RadialGradient(
      colors: [
        Color(0xFF6A11CB),
        Color(0xFF2575FC)
      ],
      begin: Alignment.topCenter,
      end: Alignment.bottomCenter
    )
  )
)
複製程式碼

等效於:

<div
  style=
  "
    width: 200px;
    height: 200px;
    background-image: radial-gradient(#6A11CBFF, #2575FCFF);
  "
>
  Hello Flutter!
</div>
複製程式碼

參考文獻

[1] Flutter從0到1構建大前端應用 何瑞君 2019年7月 ISBN: 978-7-121-36179-1 p48~p51