1. 程式人生 > >Flutter 基礎元件之 Row、Column

Flutter 基礎元件之 Row、Column

1 Row

Row 是一個可以沿水平方向展示它的子元件的元件。

它還可以靈活佈局,如果要讓某個子元件填充滿剩餘剩餘空間,請使用 Expanded 元件包裹該元件即可。

Row 元件是不可以滾動的,所以在 Row 元件中一般不會放置過多子元件,如果需要滾動的話應該考慮使用 ListView。

如果需要垂直展示,應該考慮 Column 元件。

如果只有一個子元件的話,應該考慮使用使用 Align 或者 Container 元件來定位這個子元件。

說了這麼多,對我來說,Row 就是一個 orientation 為 horizontal 的 LinearLayout。

 

1.1 構造方法

Row({Key key, MainAxisAlignment mainAxisAlignment: MainAxisAlignment.start, MainAxisSize mainAxisSize: MainAxisSize.max, CrossAxisAlignment crossAxisAlignment: CrossAxisAlignment.center, TextDirection textDirection, VerticalDirection verticalDirection: VerticalDirection.down, TextBaseline textBaseline, List<Widget> children: const [] })

Row 元件只有這一個構造方法,並且也沒有什麼必傳引數,所以說 Row 元件其實是很簡單的。

 

1.2 常用屬性

crossAxisAlignment:子元件沿著 Cross 軸(在 Row 中是縱軸)如何擺放,其實就是子元件對齊方式,可選值有:
    CrossAxisAlignment.start:子元件在 Row 中頂部對齊。
    CrossAxisAlignment.end:子元件在 Row 中底部對齊。
    CrossAxisAlignment.center:子元件在 Row 中居中對齊。
    CrossAxisAlignment.stretch:拉伸填充滿父佈局。
    CrossAxisAlignment.baseline:在 Row 元件中會報錯。

mainAxisAlignment:子元件沿著 Main 軸(在 Row 中是橫軸)如何擺放,其實就是子元件排列方式,可選值有:
    MainAxisAlignment.start:靠左排列。
    MainAxisAlignment.end:靠右排列。
    MainAxisAlignment.center:居中排列。
    MainAxisAlignment.spaceAround:每個子元件左右間隔相等,也就是 margin 相等。
    MainAxisAlignment.spaceBetween:兩端對齊,也就是第一個子元件靠左,最後一個子元件靠右,剩餘元件在中間平均分散排列。
    MainAxisAlignment.spaceEvenly:每個子元件平均分散排列,也就是寬度相等。

mainAxisSize:Main 軸大小,可選值有:
    MainAxisSize.max:相當於 Android 的 match_parent。
    MainAxisSize.min:相當於 Android 的 wrap_content。

textBaseline:不太理解。

textDirection:子元件排列順序,可選值有:
    TextDirection.ltr:從左往右開始排列。
    TextDirection.rtl:從右往左開始排列。

verticalDirection:確定如何在垂直方向擺放子元件,以及如何解釋 start 和 end,指定 height 可以看到效果,可選值有:
    VerticalDirection.up:Row 從下至上開始擺放子元件,此時我們看到的底部其實是頂部。
    VerticalDirection.down:Row 從上至下開始擺放子元件,此時我們看到的頂部就是頂部。

children:子元件,值是一個 Widget 陣列。

 

下面是一個設定了上述屬性的 Demo:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return MaterialApp(
      title: "Row",
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        appBar: AppBar(
          title: Text("Row"),
        ),
        body: Container(
          height: 300,
          child: Row(
            //子元件沿著 Cross 軸(在 Row 中是縱軸)如何擺放,其實就是子元件對齊方式,可選值有:
            //CrossAxisAlignment.start:子元件在 Row 中頂部對齊
            //CrossAxisAlignment.end:子元件在 Row 中底部對齊
            //CrossAxisAlignment.center:子元件在 Row 中居中對齊
            //CrossAxisAlignment.stretch:拉伸填充滿父佈局
            //CrossAxisAlignment.baseline:在 Row 元件中會報錯
            crossAxisAlignment: CrossAxisAlignment.start,
            //子元件沿著 Main 軸(在 Row 中是橫軸)如何擺放,其實就是子元件排列方式,可選值有:
            //MainAxisAlignment.start:靠左排列
            //MainAxisAlignment.end:靠右排列
            //MainAxisAlignment.center:居中排列
            //MainAxisAlignment.spaceAround:每個子元件左右間隔相等,也就是 margin 相等
            //MainAxisAlignment.spaceBetween:兩端對齊,也就是第一個子元件靠左,最後一個子元件靠右,剩餘元件在中間平均分散排列
            //MainAxisAlignment.spaceEvenly:每個子元件平均分散排列,也就是寬度相等
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            //Main 軸大小,可選值有:
            //MainAxisSize.max:相當於 Android 的 match_parent
            //MainAxisSize.min:相當於 Android 的 wrap_content
            mainAxisSize: MainAxisSize.max,
            //不太理解
//            textBaseline: TextBaseline.alphabetic,
            //子元件排列順序,可選值有:
            //TextDirection.ltr:從左往右開始排列
            //TextDirection.rtl:從右往左開始排列
            textDirection: TextDirection.ltr,
            //確定如何在垂直方向擺放子元件,以及如何解釋 start 和 end,指定 height 可以看到效果,可選值有:
            //VerticalDirection.up:Row 從下至上開始擺放子元件,此時我們看到的底部其實是頂部
            //VerticalDirection.down:Row 從上至下開始擺放子元件,此時我們看到的頂部就是頂部
            verticalDirection: VerticalDirection.down,
            children: <Widget>[
              Container(
                color: Color(0xFFFF0000),
                child: Text(
                  "Text1",
                  style: TextStyle(fontSize: 30.0),
                ),
              ),
              Container(
                color: Color(0xFFFFFF00),
                child: Text(
                  "Text2",
                  style: TextStyle(fontSize: 30.0),
                ),
              ),
              Container(
                color: Color(0xFF00FF00),
                child: Text(
                  "Text3",
                  style: TextStyle(fontSize: 30.0),
                ),
              ),
              Container(
                color: Color(0xFF0000FF),
                child: Text(
                  "Text4",
                  style: TextStyle(fontSize: 30.0),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

 

執行效果如下:

 

可以看到的是 4 個子元件的寬度是包裹了文字,有時候我們希望它們能夠平分 Row 的寬度,這時候只需要用 Expanded 元件包裹一下子元件就行了:

            children: <Widget>[
              Expanded(
                  child: Container(
                color: Color(0xFFFF0000),
                child: Text(
                  "Text1",
                  style: TextStyle(fontSize: 30.0),
                ),
              )),
              Expanded(
                  child: Container(
                color: Color(0xFFFFFF00),
                child: Text(
                  "Text2",
                  style: TextStyle(fontSize: 30.0),
                ),
              )),
              Expanded(
                  child: Container(
                color: Color(0xFF00FF00),
                child: Text(
                  "Text3",
                  style: TextStyle(fontSize: 30.0),
                ),
              )),
              Expanded(
                  child: Container(
                color: Color(0xFF0000FF),
                child: Text(
                  "Text4",
                  style: TextStyle(fontSize: 30.0),
                ),
              )),

 

執行效果如下:

 

Expanded 元件的使用很簡單,除了一個必傳的引數 child 以為,還有一個 flex 屬性,它就相當於 LinearLayout 中的 weight,預設是 1,如果指定為 2 就表示它包裹的子元件佔據的空間為總數的兩份,如:

            children: <Widget>[
              Expanded(
                  child: Container(
                color: Color(0xFFFF0000),
                child: Text(
                  "Text1",
                  style: TextStyle(fontSize: 30.0),
                ),
              )),
              Expanded(
                  child: Container(
                color: Color(0xFFFFFF00),
                child: Text(
                  "Text2",
                  style: TextStyle(fontSize: 30.0),
                ),
              )),
              Expanded(
                  child: Container(
                color: Color(0xFF00FF00),
                child: Text(
                  "Text3",
                  style: TextStyle(fontSize: 30.0),
                ),
              )),
              Expanded(
                  flex: 2,
                  child: Container(
                    color: Color(0xFF0000FF),
                    child: Text(
                      "Text4",
                      style: TextStyle(fontSize: 30.0),
                    ),
                  )),
            ],

一共是 4 個子元件,最後一個子元件指定了 flex 為 2,其他沒有指定 flex 屬性的子元件預設 flex 為 1,1+1+1+2 = 5,總共把 Row 元件的寬度分為 5 份,最後一個子元件的寬度佔 5 份中的 2 份,其餘子元件各佔 5 份中的 1 份:

 

2 Column

Column 就相當於一個 orientation 為 vertical 的 LinearLayout。它的用法完全與 Row 一樣,可以說會了 Row 元件就會了 Column 元件,所以不詳細介紹,將上面 Demo 中的 Row 改為 Column 看看效果:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return MaterialApp(
      title: "Row",
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        appBar: AppBar(
          title: Text("Row"),
        ),
        body: Container(
          child: Column(
            //子元件沿著 Cross 軸(在 Row 中是縱軸)如何擺放,其實就是子元件對齊方式,可選值有:
            //CrossAxisAlignment.start:子元件在 Row 中頂部對齊
            //CrossAxisAlignment.end:子元件在 Row 中底部對齊
            //CrossAxisAlignment.center:子元件在 Row 中居中對齊
            //CrossAxisAlignment.stretch:拉伸填充滿父佈局
            //CrossAxisAlignment.baseline:在 Row 元件中會報錯
            crossAxisAlignment: CrossAxisAlignment.start,
            //子元件沿著 Main 軸(在 Row 中是橫軸)如何擺放,其實就是子元件排列方式,可選值有:
            //MainAxisAlignment.start:靠左排列
            //MainAxisAlignment.end:靠右排列
            //MainAxisAlignment.center:居中排列
            //MainAxisAlignment.spaceAround:每個子元件左右間隔相等,也就是 margin 相等
            //MainAxisAlignment.spaceBetween:兩端對齊,也就是第一個子元件靠左,最後一個子元件靠右,剩餘元件在中間平均分散排列
            //MainAxisAlignment.spaceEvenly:每個子元件平均分散排列,也就是寬度相等
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            //Main 軸大小,可選值有:
            //MainAxisSize.max:相當於 Android 的 match_parent
            //MainAxisSize.min:相當於 Android 的 wrap_content
            mainAxisSize: MainAxisSize.max,
            //不太理解
//            textBaseline: TextBaseline.alphabetic,
            //子元件排列順序,可選值有:
            //TextDirection.ltr:從左往右開始排列
            //TextDirection.rtl:從右往左開始排列
            textDirection: TextDirection.ltr,
            //確定如何在垂直方向擺放子元件,以及如何解釋 start 和 end,指定 height 可以看到效果,可選值有:
            //VerticalDirection.up:Row 從下至上開始擺放子元件,此時我們看到的底部其實是頂部
            //VerticalDirection.down:Row 從上至下開始擺放子元件,此時我們看到的頂部就是頂部
            verticalDirection: VerticalDirection.down,
            children: <Widget>[
              Expanded(
                  child: Container(
                width: double.infinity,
                color: Color(0xFFFF0000),
                child: Text(
                  "Text1",
                  style: TextStyle(fontSize: 30.0),
                ),
              )),
              Expanded(
                  child: Container(
                width: double.infinity,
                color: Color(0xFFFFFF00),
                child: Text(
                  "Text2",
                  style: TextStyle(fontSize: 30.0),
                ),
              )),
              Expanded(
                  child: Container(
                width: double.infinity,
                color: Color(0xFF00FF00),
                child: Text(
                  "Text3",
                  style: TextStyle(fontSize: 30.0),
                ),
              )),
              Expanded(
                  flex: 2,
                  child: Container(
                    width: double.infinity,
                    color: Color(0xFF0000FF),
                    child: Text(
                      "Text4",
                      style: TextStyle(fontSize: 30.0),
                    ),
                  )),
            ],
          ),
        ),
      ),
    );
  }
}

 

執行效果如下:

 

3 總結

Flutter 將 Android 中一個 LinearLayout 橫縱向拆成了兩個元件,還是覺得怪麻煩的,還好兩個元件的屬性沒有上面區別,我忍了。Row 和 Column 是最基本的佈局元件,算是基礎中的基礎呀。