本文主要介紹Flutter中很是常見的Container,列舉了一些實際例子介紹如何使用。html
A convenience widget that combines common painting, positioning, and sizing widgets.git
Container在Flutter中太常見了。官方給出的簡介,是一個結合了繪製(painting)、定位(positioning)以及尺寸(sizing)widget的widget。github
能夠得出幾個信息,它是一個組合的widget,內部有繪製widget、定位widget、尺寸widget。後續看到的很多widget,都是經過一些更基礎的widget組合而成的。less
Container的組成以下:ide
Container的繪製的過程以下:函數
Container自身尺寸的調節分兩種狀況:佈局
因爲Container組合了一系列的widget,這些widget都有本身的佈局行爲,所以Container的佈局行爲有時候是比較複雜的。學習
通常狀況下,Container會遵循以下順序去嘗試佈局:ui
進一步說:this
另外,margin以及padding屬性也會影響到佈局。
Object > Diagnosticable > DiagnosticableTree > Widget > StatelessWidget > Container
從繼承關係能夠看出,Container是一個StatelessWidget。Container並非一個最基礎的widget,它是由一系列的基礎widget組合而成。
構造函數以下:
Container({ Key key, this.alignment, this.padding, Color color, Decoration decoration, this.foregroundDecoration, double width, double height, BoxConstraints constraints, this.margin, this.transform, this.child, })
平時使用最多的,也就是padding、color、width、height、margin屬性。
key:Container惟一標識符,用於查找更新。
alignment:控制child的對齊方式,若是container或者container父節點尺寸大於child的尺寸,這個屬性設置會起做用,有不少種對齊方式。
padding:decoration內部的空白區域,若是有child的話,child位於padding內部。padding與margin的不一樣之處在於,padding是包含在content內,而margin則是外部邊界,設置點擊事件的話,padding區域會響應,而margin區域不會響應。
color:用來設置container背景色,若是foregroundDecoration設置的話,可能會遮蓋color效果。
decoration:繪製在child後面的裝飾,設置了decoration的話,就不能設置color屬性,不然會報錯,此時應該在decoration中進行顏色的設置。
foregroundDecoration:繪製在child前面的裝飾。
width:container的寬度,設置爲double.infinity能夠強制在寬度上撐滿,不設置,則根據child和父節點二者一塊兒佈局。
height:container的高度,設置爲double.infinity能夠強制在高度上撐滿。
constraints:添加到child上額外的約束條件。
margin:圍繞在decoration和child以外的空白區域,不屬於內容區域。
transform:設置container的變換矩陣,類型爲Matrix4。
child:container中的內容widget。
new Container( constraints: new BoxConstraints.expand( height:Theme.of(context).textTheme.display1.fontSize * 1.1 + 200.0, ), decoration: new BoxDecoration( border: new Border.all(width: 2.0, color: Colors.red), color: Colors.grey, borderRadius: new BorderRadius.all(new Radius.circular(20.0)), image: new DecorationImage( image: new NetworkImage('http://h.hiphotos.baidu.com/zhidao/wh%3D450%2C600/sign=0d023672312ac65c67506e77cec29e27/9f2f070828381f30dea167bbad014c086e06f06c.jpg'), centerSlice: new Rect.fromLTRB(270.0, 180.0, 1360.0, 730.0), ), ), padding: const EdgeInsets.all(8.0), alignment: Alignment.center, child: new Text('Hello World', style: Theme.of(context).textTheme.display1.copyWith(color: Colors.black)), transform: new Matrix4.rotationZ(0.3), )
這是官方文檔給出例子的一個變種,包含屬性比較全,能夠看下其用法。實際運行效果以下:
其中decoration能夠設置邊框、背景色、背景圖片、圓角等屬性,很是實用。對於transform這個屬性,通常有過其餘平臺開發經驗的,都大體瞭解,這種變換,通常不是變換的實際位置,而是變換的繪製效果,也就是說它的點擊以及尺寸、間距等都是按照未變換前的。
decoration = decoration ?? (color != null ? new BoxDecoration(color: color) : null),
能夠看出,對於顏色的設置,最後都是轉換爲decoration來進行繪製的。若是同時包含decoration和color兩種屬性,則會報錯。
@override Widget build(BuildContext context) { Widget current = child; if (child == null && (constraints == null || !constraints.isTight)) { current = new LimitedBox( maxWidth: 0.0, maxHeight: 0.0, child: new ConstrainedBox(constraints: const BoxConstraints.expand()) ); } if (alignment != null) current = new Align(alignment: alignment, child: current); final EdgeInsetsGeometry effectivePadding = _paddingIncludingDecoration; if (effectivePadding != null) current = new Padding(padding: effectivePadding, child: current); if (decoration != null) current = new DecoratedBox(decoration: decoration, child: current); if (foregroundDecoration != null) { current = new DecoratedBox( decoration: foregroundDecoration, position: DecorationPosition.foreground, child: current ); } if (constraints != null) current = new ConstrainedBox(constraints: constraints, child: current); if (margin != null) current = new Padding(padding: margin, child: current); if (transform != null) current = new Transform(transform: transform, child: current); return current; }
Container的build函數不長,繪製也是一個線性的判斷的過程,一層一層的包裹着widget,去實現不一樣的樣式。
最裏層的是child,若是爲空或者其餘約束條件,則最裏層包含的爲一個LimitedBox,而後依次是Align、Padding、DecoratedBox、前景DecoratedBox、ConstrainedBox、Padding(實現margin效果)、Transform。
Container的源碼自己並不複雜,複雜的是它的各類佈局表現。咱們謹記住一點,若是內部不設置約束,則按照父節點儘量的擴大,若是內部有約束,則按照內部來。
Container算是目前項目中,最常常用到的一個widget。在實際使用過程當中,筆者在如下狀況會使用到Container,固然並非絕對的,也能夠經過其餘widget來實現。
接下來咱們試着去作一個圓角按鈕,它包含如下特性:
根據上面介紹,利用decoration這個屬性,基本上就能夠完成效果了,至於點擊效果以及點擊回調,則使用一個GestureDetector就能夠完成了。實際的例子很是簡單,在這裏就不貼代碼了。實際運行效果以下所示:
這個小控件,寫起來很簡單,自己沒有什麼難度,只是純粹的介紹了Container的使用方法,可是有一個地方須要注意的。在控件的deactivate狀態,咱們須要將控件的屬性初始到最開始的狀態,例如在本例中,有以下代碼:
@override void deactivate() { super.deactivate(); currentColor = widget.backgroundColor; }
這麼作是爲何了?是由於在點擊按鈕進行頁面跳轉的時候,按鈕處在點擊態,當咱們返回的時候,頁面仍是處在點擊態,這顯然就不正確了,所以須要咱們手動的在deactivate狀態下,將控件恢復到初始狀態。可是呢,這個設置顏色,並非說在deactivate的時候,就立馬去刷新控件,而是在下次再進入這個頁面的時候,再次運行build的時候,會按照這個初始值進行繪製,也就是恢復到了最開始的狀態。
代碼Github地址,這是一個系列的項目,若是不出意外,會將Flutter中常見的二十多種佈局widget都介紹一下。
筆者建了一個flutter學習相關的項目,github地址,裏面包含了筆者寫的關於flutter學習相關的一些文章,會按期更新,也會上傳一些學習demo,歡迎你們關注。