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 是最基本的佈局元件,算是基礎中的基礎呀。