Flutter之Container用法詳解

小川同志發表於2019-02-15

簡書地址:huoshe2019

最近開始接觸Flutter,網上對Flutter評價很高,加上是谷歌這種大公司研發推廣的,決定先入坑。

廢話不多說,直奔主題!學習框架,首先要將裡面常用控制元件熟練使用,後面可以逐步深入、究其原理。

這裡主要講解Container相關屬性以及使用方法(github地址:Flutter):

  • Color Property
  • Child Property
  • Alignment Property
  • Constraints Property
  • Margin Property
  • Padding Property
  • Decoration Property
  • ForegroundDecoration Property
  • Transform Property

前言

Container類似於iOS中的UIView,具有繪製定位調整大小功能。通常用來裝載其它子控制元件,假如Container沒有子控制元件,它將自動填充整個螢幕;反之,會根據子控制元件大小,調整自身大小,從而達到自適應效果。

注意:

使用Container時,通常要有一個父控制元件,一般情況下不單獨使用Container。常用的父控制元件有Center widget、Padding Widget、Column Widget、Row Widget、Scaffold Widget。

一、Color Property

這個屬性用於設定Container的背景顏色,類似於iOS中的UIView的backgroundColor。使用如下:

  • Colors Class
//Container顏色屬性之Colors
class Color_Property_Colors extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    return Center(
        child: Container(
          //color: Colors.green,//正常顏色
          //color:Colors.green[200],//帶有陰影(相當於是透明度)
          color: Colors.green.shade200,//同上
        ),
    );
  }
}
複製程式碼

呈現效果如下:

圖1 Container之Colors屬性
  • Color Class
//Container顏色屬性之Color
class Color_Property_Color extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Container(
        //color: Color(0xFFFFFFFF),//一定是8位,否則報錯
        //color: Color.fromARGB(255, 66, 165, 245),
        color: Color.fromRGBO(66, 165, 245, 1.0),//作用同上
      ),
    );
  }
}
複製程式碼

呈現效果如下:

圖2 Container之Color屬性

注意:

1、使用8位16進位制而不是6位
2、.fromARGB含義
A = Alpha or opacity, R = Red, G = Green, B = Blue
3、.fromRGBO含義
R = Red, G = Green, B = Blue, O = Opacity

二、Child Property

如前言所述,如果Container裡面沒有子控制元件,它就會填充整個螢幕;如果有子控制元件,Container就會自動適應子控制元件大小
另外,Container只能容納一個子控制元件,如果想容納更多的子控制元件,可以將子控制元件設定為Row、Column、Stack(這三個子控制元件都有一個children屬性)

  • 新增子控制元件
//Container屬性之Child
class Child_Property extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Container(
        color: Color.fromRGBO(66, 165, 245, 1.0),
        child: Text("Flutter Cheatsheet"),
      ),
    );
  }
}
複製程式碼

呈現效果如下:

圖3 新增子控制元件

三、Alignment Property

Alignment屬性主要是針對於Container內部的子控制元件佈局。
主要有以下幾個屬性:Alignment、FractionalOffset、AlignmentDirectional

  • Alignment
    程式碼如下:
//Container屬性之Alignment
class Alignment_Property extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Container(
        color: Color.fromARGB(255, 66, 165, 245),
        child: Text("Flutter Cheatsheet",
             style: TextStyle(
               fontSize: 30.0
             ),
        ),
        //不加這句話,Container會自適應child大小;加上以後會充滿螢幕
        //alignment: Alignment(0.0, 0.0),
        alignment: Alignment.center,//等價於上面
      ),
    );
  }
}
複製程式碼

效果如下:

圖4 Container屬性之Alignment

Alignment座標系圖如下:

圖5 Alignment座標系

常用等價屬性:

Alignment.bottomCenter 對應 Alignment(0.0, 1.0)

Alignment.bottomLeft 對應 Alignment(-1.0, 1.0)

Alignment.bottomRight 對應 Alignment(1.0, 1.0)

Alignment.center 對應 Alignment(0.0, 0.0)

Alignment.centerLeft 對應 Alignment(-1.0, 0.0)

Alignment.centerRight 對應 Alignment(1.0, 0.0)

Alignment.topCenter 對應 Alignment(0.0, -1.0)

Alignment.topLeft 對應 Alignment(-1.0, -1.0)

Alignment.topRight 對應 Alignment(1.0, -1.0)

  • FractionalOffset
    這個屬性跟上面講的Alignment非常相似,唯一的不同就是座標系:
    Alignment座標系是X:-1.0–1.0;Y:-1.0–1.0,
    FractionalOffset座標系是X:0.0–1.0,Y:0.0–1.0。

FractionalOffset座標系圖如下:

圖6 FractionalOffset座標系

程式碼如下:

//Container屬性之FractionalOffset
class Alignment_FractionalOffset extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Container(
        color: Color.fromARGB(255, 66, 165, 245),
        child: Text("Flutter Cheatsheet",
          style: TextStyle(
              fontSize: 30.0
          ),
        ),
        //不加這句話,Container會自適應child大小;加上以後會充滿螢幕
        //alignment: FractionalOffset(0.5, 0.5),
        alignment: FractionalOffset.center,//等價於上面
      ),
    );
  }
}
複製程式碼

常用等價屬性如下

FractionalOffset.bottomCenter 對應 FractionalOffset(0.5, 1.0)

FractionalOffset.bottomLeft 對應 FractionalOffset(0.0, 1.0)

FractionalOffset.bottomRight 對應 FractionalOffset(1.0, 1.0)

FractionalOffset.center 對應 FractionalOffset(0.5, 0.5)

FractionalOffset.centerLeft 對應 FractionalOffset(0.0, 0.5)

FractionalOffset.centerRight 對應 FractionalOffset(1.0, 0.5)

FractionalOffset.topCenter 對應 FractionalOffset(0.5, 0.0)

FractionalOffset.topLeft 對應 FractionalOffset(0.0, 0.0)

FractionalOffset.topRight 對應 FractionalOffset(1.0, 0.0)

  • AlignmentDirectional
    說到這個屬性,就要提到一個小插曲:
    網上說AlignmentDirectional有2個座標系,是因為TextDirection.ltr和TextDirection.rtl,但是經過本人的親身實驗,這種觀點是不對的,不知道是不是由於官方官方框架更新的原。
    最終結論:這個屬性跟Alignment用法是完全一樣(既然完全一樣,何必多此一舉呢?)。

座標系圖如下:

圖7 AlignmentDirectional座標系

程式碼如下:

//Container屬性之AlignmentDirectional
class Alignment_AlignmentDirectional extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Container(
        color: Color.fromARGB(255, 66, 165, 245),
        child: Text("Flutter",
          style: TextStyle(
              fontSize: 15.0
          ),
          //textDirection: TextDirection.ltr,//正常,從左向右(不影響alignment)
          textDirection: TextDirection.ltr,//從右向左(不影響alignment)
        ),
        //不加這句話,Container會自適應child大小;加上以後會充滿螢幕
        alignment:AlignmentDirectional(-1.0, 1.0),
        //alignment: AlignmentDirectional.bottomStart,//等價於上面
      ),
    );
  }
}
複製程式碼

常用等價屬性:

AlignmentDirectional.bottomCenter 對應 AlignmentDirectional(0.0, 1.0)

AlignmentDirectional.bottomEnd 對應 AlignmentDirectional(1.0, 1.0)

AlignmentDirectional.bottomStart 對應 AlignmentDirectional(-1.0, 1.0)

AlignmentDirectional.center 對應 AlignmentDirectional(0.0, 0.0)

AlignmentDirectional.centerEnd 對應 AlignmentDirectional(1.0, 0.0)

AlignmentDirectional.centerStart 對應 AlignmentDirectional(-1.0, 0.0)

AlignmentDirectional.topCenter 對應 AlignmentDirectional(0.0, -1.0)

AlignmentDirectional.topEnd 對應 AlignmentDirectional(1.0, -1.0)

AlignmentDirectional.topStart 對應 AlignmentDirectional(-1.0, -1.0)

四、Constraints Property

佈局屬性,主要講的是怎麼確定控制元件的大小;其中經常使用的就是BoxConstraint。BoxConstraint包含minWidth、maxWidth、minHeight、maxHeight,詳細介紹如下:

  • Container無子控制元件(場景1)
    程式碼如下:
//Container屬性之Constraints Property
class Constraints_Property extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Container(
        color: Color.fromARGB(255, 66, 165, 245),
        alignment: AlignmentDirectional(0.0, 0.0),
        child: Container(
          color: Colors.green,
          constraints: BoxConstraints(
            maxHeight: 300,
            maxWidth: 200,
            minWidth: 150,
            minHeight: 150,
          ),
        ),
      ),
    );
  }
}
複製程式碼

呈現效果如下:

圖8 Container之Constraints無子控制元件

前面說過如果Container沒有子控制元件,Container將填充整個螢幕,但是這裡設定maxHeight、maxWidth。

  • Container有子控制元件(場景2)
    程式碼如下:
//Container屬性之Constraints(有子控制元件)
class Constraints_Property_HasChild extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Container(
        color: Color.fromARGB(255, 66, 165, 245),
        alignment: AlignmentDirectional(0.0, 0.0),
        child: Container(
          color: Colors.green,
          child: Text("Flutter"),
          constraints: BoxConstraints(
            maxHeight: 300,
            maxWidth: 200,
            minWidth: 150,
            minHeight: 150,
          ),
        ),
      ),
    );
  }
}
複製程式碼

呈現效果如下:

圖9 Container之Constraints有子控制元件

這裡雖然有一個子控制元件,Container會調整自身大小來適應內部子控制元件,但是由於設定了min-width和min-height。所以Container不會完全和子控制元件一樣大,除非子控制元件尺寸大於min-width和min-height。

嘗試更改子控制元件大小,程式碼如下:

//Container屬性之Constraints(有子控制元件)
class Constraints_Property_HasChild extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Container(
        color: Color.fromARGB(255, 66, 165, 245),
        alignment: AlignmentDirectional(0.0, 0.0),
        child: Container(
          color: Colors.green,
          //child: Text("Flutter"),
          child: Text("Flutter Cheatsheet Flutter Cheatsheet"),
          constraints: BoxConstraints(
            maxHeight: 300,
            maxWidth: 200,
            minWidth: 150,
            minHeight: 150,
          ),
        ),
      ),
    );
  }
}
複製程式碼

呈現效果圖如下:

圖10 Container之Constraints有子控制元件

從上面這張圖可以看出Container不能超出max-width和max-height。

  • Container有子控制元件(場景3)
    當Container有子控制元件,我們想讓Container不去適應子控制元件,而是充滿整個螢幕或父控制元件,怎麼辦?
    答案就是使用BoxConstraints.expand()。
    程式碼如下:
//Container屬性之Constraints(有子控制元件、充滿整個螢幕)
class Constraints_Property_HasChild_AllScreen extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Container(
        color: Color.fromARGB(255, 66, 165, 245),
        alignment: AlignmentDirectional(0.0, 0.0),
        child: Container(
          color: Colors.green,
          //child: Text("Flutter"),
          child: Text("Flutter"),
          constraints: BoxConstraints.expand(),
        ),
      ),
    );
  }
} 
複製程式碼

呈現效果如下:

圖11 Container之Constraints有子控制元件

此時發現Container是充滿整個螢幕的,我們也可以限制充滿螢幕大小,比如說1/2寬、1/3高等。

五、Margin Property

跟前端的css類似,這個Margin指的是相鄰控制元件之間的距離,主要是用EdgeInsets。

  • EdgeInsets.all()
  • EdgeInsets.symmetric()
  • EdgeInsets.fromLTRB()
  • EdgeInsets.only()

詳細如下:

  • EdgeInsets.all()
    程式碼如下:
//EdgeInsets.all()
class Margin_Property_EdgeInsets_all extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Container(
        color: Color.fromARGB(255, 66, 165, 245),
        alignment: AlignmentDirectional(0.0, 0.0),
        child: Container(
          color: Colors.green,
          margin: EdgeInsets.all(20.0),
        ),
      ),
    );
  }
}
複製程式碼

呈現效果如下:

圖12 Margin之EdgeInsets.all
  • EdgeInsets.symmetric()
    這個主要用於新增垂直和水平方向上的約束。
    程式碼如下:
//EdgeInsets.symmetric()
class Margin_Property_EdgeInsets_symmetric extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Container(
        color: Color.fromARGB(255, 66, 165, 245),
        alignment: AlignmentDirectional(0.0, 0.0),
        child: Container(
          color: Colors.green,
          margin: EdgeInsets.symmetric(
            vertical: 20.0,
            horizontal: 50.0,
          ),
        ),
      ),
    );
  }
}
複製程式碼

呈現效果如下:

圖13 Margin之EdgeInsets. symmetric
  • EdgeInsets.fromLTRB()
    這個主要設定left, top, right,bottom邊距。
    程式碼如下:
//EdgeInsets.fromLTRB()
class Margin_Property_EdgeInsets_fromLTRB extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Container(
        color: Color.fromARGB(255, 66, 165, 245),
        alignment: AlignmentDirectional(0.0, 0.0),
        child: Container(
          color: Colors.green,
          margin: EdgeInsets.fromLTRB(20.0, 30.0, 40.0, 50.0)
        ),
      ),
    );
  }
}
複製程式碼

呈現效果:

圖14  Margin之EdgeInsets. fromLTRB
  • EdgeInsets.only()
    用於設定哪些是非零的,不設定預設是零。
    程式碼如下:
//EdgeInsets.only()
class Margin_Property_EdgeInsets_only extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Container(
        color: Color.fromARGB(255, 66, 165, 245),
        alignment: AlignmentDirectional(0.0, 0.0),
        child: Container(
            color: Colors.green,
            margin: EdgeInsets.only(
              left: 20.0,
              bottom: 40.0,
              top: 50.0,
            )
        ),
      ),
    );
  }
}
複製程式碼

呈現效果如下:

圖15  Margin之EdgeInsets.only

六、Padding Property

這個用於設定主控制元件內部子控制元件之間的間距。和Margin一樣,利用到EdgeInsets。
程式碼如下:

//EdgeInsets.all
class Padding_Property_EdgeInsets_all extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Container(
        color: Color.fromARGB(255, 66, 165, 245),
        alignment: AlignmentDirectional(0.0, 0.0),
        child: Container(
          margin: EdgeInsets.only(
            left: 20.0,
            bottom: 40.0,
            top: 50.0,
          ),
          padding: EdgeInsets.all(10.0),//設定內部Text控制元件邊距
          color: Colors.green,
          child: Text("Flutter Cheatsheet"),
          //不設定這個Container和子控制元件一樣大小、這樣margin設定也就沒有意義了
          constraints: BoxConstraints.expand(),
        ),
      ),
    );
  }
}
複製程式碼

呈現效果如下:

圖16 Padding之EdgeInsets.all

七、Decoration Property

  • BoxDecoration Class
  • FlutterLogoDecoration Class
  • ShapeDecoration Class
  • UnderlineTabIndicator Class
    由於涉及篇幅較長,後續會重新文章詳細講解,敬請關注簡書

八、ForegroundDecoration Property

  • BoxDecoration Class
  • FlutterLogoDecoration Class
  • ShapeDecoration Class
  • UnderlineTabIndicator Class
    由於涉及篇幅較長,後續會重新文章詳細講解,敬請關注簡書

九、Transform Property

在Container屬性中新增transform屬性,並使用Matrix類設定transform的值,即可達到各種變換效果,程式碼如下:

//Transform Property
class Transform_Property extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Color.fromARGB(255, 66, 165, 245),
      alignment: AlignmentDirectional(0.0, 0.0),
      child: Container(
        padding: EdgeInsets.all(40.0),
        color: Colors.green,
        child: Text("Flutter Cheatsheet"),  
        transform: Matrix4.rotationZ(0.5),
      ),
    );
  }
}
複製程式碼

效果圖如下:

圖17 Transform Property

參考文章:

Flutter — Container Cheat Sheet

簡書地址

相關文章