Flutter 基礎元件之 Container
官方簡介中,說 Container 元件是一個方便繪製、定位和調整子元件大小的元件。
首先 Container 會在 child 子元件周圍填充 padding(包括 decoration 中存在的 border),然後會根據約束 constraints 來決定子元件的寬高,最後 Container 會根據 margin 來新增周圍的空白空間。
在繪製過程中,Container 先會應用矩陣變換 transform,然後繪製 decoration,然後繪製 child 子元件,最後繪製 foregroundDecoration。
Container 如果沒有子元件的話會嘗試儘可能地大,除非傳入的約束 constraints 是無限的,如果是這種情況,Container 會盡可能地小。Containers with children size themselves to their children. The width
height
, and constraints arguments to the constructor override this.(這句話看不懂了,T_T)。
總的來說,Container 是一種很常用的元件,我們可以用它來包裹任意元件,之前說Text 元件裡面設定 backgroundColor 會讓有的文字顯示有問題,如果用 Container 來包裹 Text 再設定背景就很方便了,而且包括圓角等樣式都可以輕鬆設定,再也不用 Android 那樣定義許多大同小異的 xml 了。
1 構造方法
Container({Key key, AlignmentGeometry alignment, EdgeInsetsGeometry padding, Color color, Decoration decoration, Decoration foregroundDecoration, double width, double height, BoxConstraints constraints, EdgeInsetsGeometry margin, Matrix4 transform, Widget child })
Container 只有這一個構造方法,並沒有必傳的引數,但是一般我們都會用它來包裹子元件,也就是一般都會設定 child 屬性。
2 常用屬性
width 和 height:寬和高,這個不用贅述。
color:背景色,值為一個 Color 物件,不能與 decoration 屬性同時設定。
margin:外邊距,值為一個 EdgeInsets 物件。EdgeInsets 物件即可呼叫EdgeInsets.all() 方法統一設定左上右下四條邊的邊距,也可以呼叫 EdgeInsets.fromLTRB() 分別設定左上右下四條邊的邊距。
padding
alignment:對齊方式,可選值(看字面意思就很好理解)有:
Alignment.topLeft:垂直靠頂部水平靠左對齊。
Alignment.topCenter:垂直靠頂部水平居中對齊。
Alignment.topRight:垂直靠頂部水平靠右對齊。
Alignment.centerLeft:垂直居中水平靠左對齊。
Alignment.center:垂直和水平居中都對齊。
Alignment.centerRight:垂直居中水平靠右對齊。
Alignment.bottomLeft:垂直靠底部水平靠左對齊。
Alignment.bottomCenter:垂直靠底部水平居中對齊。
Alignment.bottomRight:垂直靠底部水平靠右對齊。
除了上面的常量之外,還可以建立 Alignment 物件指定 x、y 偏移量。
decoration:裝飾,背景邊框等,不能與 color 屬性同時設定,會繪製在 child 之下,也就是會被 child 覆蓋,具體 API 參考 2.1
BoxDecoration。
foregroundDecoration:也是裝飾,但是會繪製在 child 之上,也就是會覆蓋 child。
constraints:約束,這個規則貌似挺複雜的,後面詳細研究。
transform:形狀變換,這個用得應該比較少,可能會在做動畫的時候用到,後面詳細研究。
child:子元件。
2.1 BoxDecoration
首先 BoxDecoration 只是 Decoration 的一個實現類,其他實現類還有 FlutterLogoDecoration、ShapeDecoration、UnderlineTabIndicator,這裡只是介紹一下常用的 BoxDecoration。
color:背景填充顏色,值為一個 Color 物件。
border:值為一個 BoxBorder 物件,該物件可以設定邊框顏色、邊框寬度、邊框樣式等。
borderRadius:邊框圓角,可以呼叫 BorderRadius.all() 統一設定四個角的圓角,也可以呼叫 BorderRadius.only() 分別設定四個角的圓角。
gradient:設定成漸變效果的背景,會覆蓋 color。
boxShadow:陰影效果,值為一個 BoxShadow 集合。
backgroundBlendMode:應該是背景混合模式,這個應該比較複雜,後面再研究。
image:使用圖片作為裝飾。
下面是一個設定了上述屬性的 demo:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
var imgUrl =
"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1545122324077&di=1b5986ad937c81c41f4c135ea1a9a026&imgtype=0&src=http%3A%2F%2Fe.hiphotos.baidu.com%2Fzhidao%2Fwh%253D450%252C600%2Fsign%3Df719f9458f01a18bf0be1a4bab1f2b3e%2Fc2fdfc039245d688a8f2cdcdacc27d1ed31b24e2.jpg";
return MaterialApp(
//是否顯示 debug 標籤
debugShowCheckedModeBanner: false,
title: "Container",
home: Scaffold(
appBar: new AppBar(
title: new Text("Container"),
),
body: new Container(
// color: new Color(0xFFFF0000),
//外邊距,值為一個 EdgeInsets 物件
margin: EdgeInsets.all(30.0),
//內間距,值為一個 EdgeInsets 物件
padding: EdgeInsets.fromLTRB(30.0, 0, 0, 0),
//對齊方式,可選值有:
//Alignment.topLeft:垂直靠頂部水平靠左對齊。
//Alignment.topCenter:垂直靠頂部水平居中對齊。
//Alignment.topRight:垂直靠頂部水平靠右對齊。
//Alignment.centerLeft:垂直居中水平靠左對齊。
//Alignment.center:垂直和水平居中都對齊。
//Alignment.centerRight:垂直居中水平靠右對齊。
//Alignment.bottomLeft:垂直靠底部水平靠左對齊。
//Alignment.bottomCenter:垂直靠底部水平居中對齊。
//Alignment.bottomRight:垂直靠底部水平靠右對齊。
//除了上面的常量之外,還可以建立 Alignment 物件指定 x、y 偏移量
alignment: Alignment.centerLeft,
//裝飾,背景邊框等,不能與 color 屬性同時設定,會繪製在 child 之下,也就是會被 child 覆蓋
decoration: new BoxDecoration(
//背景填充顏色
color: new Color(0xFFFF0000),
//背景邊框
border: new Border.all(
//邊框顏色
color: new Color(0xFFFFFF00),
//邊框寬度
width: 5),
//邊框圓角
borderRadius: new BorderRadius.only(
topLeft: new Radius.circular(5.0),
topRight: new Radius.circular(10.0),
bottomLeft: new Radius.circular(15.0),
bottomRight: new Radius.circular(20.0)),
//漸變效果,會覆蓋 color
gradient: new LinearGradient(colors: [
new Color(0xFFFFDEAD),
new Color(0xFF98FB98),
new Color(0xFF6495ED)
]),
//陰影效果
boxShadow: [new BoxShadow(color:Color(0xFFFF0000),blurRadius: 5.0)],
//應該是背景混合模式,這個應該比較複雜,後面再研究
backgroundBlendMode: BlendMode.color,
//圖片
// image: new DecorationImage(image: new NetworkImage(imgUrl))
),
//也是裝飾,但是會繪製在 child 之上,也就是會覆蓋 child
// foregroundDecoration: new BoxDecoration(
// image: new DecorationImage(image: new NetworkImage(imgUrl))
// ),
//約束,這個規則貌似挺複雜的,後面詳細研究
constraints: new BoxConstraints(maxWidth: 300.0, maxHeight: 400.0),
//形狀變換,這個用得應該也比較少,可能會在做動畫的時候用到,後面詳細研究
transform: new Matrix4.skewY(0.3),
//子元件
child: new Text(
"Hello World",
textDirection: TextDirection.ltr,
style: new TextStyle(color: new Color(0xFFFFFFFF), fontSize: 40.0),
),
),
),
);
}
}
執行效果如下:
可以看到我們給 Container 設定了 margin 屬性,所以上下左右有一些外邊距,然後雖然設定了對齊方式 alignment 為 centerLeft,但是又設定了左邊距為 100,所有左邊又有一些內間距,同時設定了約束 constraints 最大寬度為 300,所有它的寬度比全屏減去外邊距還要小一些,我們還設定了邊框、圓角、漸變背景、矩陣變換等一系列讓其效果更豐富的屬性,這些設定也並不麻煩,最終就是上面這個效果。
3 總結
在學習 Text 元件的時候覺得想給它設定圓角背景什麼的無從下手,但是如果用 Container 一包裹的話簡直不要太簡單,而且 Flutter 實現圓角的方式比起 Android 那種寫很多 xml 檔案的方式,讓我一下就愛上它了。