在Flutter中,號稱一切皆widget,手勢是Widget,動畫是Widget,UI更是Widget,今天咱們就來講說Widgets裏比較特殊的一個,Container。html
Container初用起來很簡單,可是裏面的邏輯又有些複雜,我也不敢說徹底吃透,因此本文初期版本仍是以總結網上各類文章爲主,再加上本身的理解,若是有不對的地方,請必定指出android
Building Layouts in Flutterpost
Dealing with box constraints in Flutter動畫
Flutter — Container Cheat Sheetui
Widgets: Containerdebug
What is a Container in Flutter?3d
Container Widget with example Flutter Tutorialorm
Understanding Flutter Layout (Box)Constraints
在flutter中,全部的功能都被分散成單一功能的widget,好比居中有Center,邊框有Padding,文字是Text,手勢是GestureDetector,他們各自維護一個功能,可是咱們商業App的UI都很精美,若是要實現一個很好的佈局,須要嵌套很是多的佈局Widget,因此Container應運而生:
A convenience widget that combines common painting, positioning, and sizing widgets.
官方文檔一語道破了container複雜的緣由,它是一個便利部件,融合了繪圖、定位和大小部件,據我所知,能夠設置大小,背景顏色,邊框,圓角,陰影,漸變,並且大小能夠有不少種狀況,時而依賴於父部件,時而依賴於子部件,時而依賴於本身,因此咱們稍後會重點說一說Container的佈局(尺寸規則,寬高)。
根據官網的介紹,Container會首先使用設置的padding來圍繞子部件,而後對padding的大小添加額外的約束(若是非空),而後容器被外部的空白區域(margin)包圍。在繪製過程當中,Container首先應用變換(transform),而後繪製裝飾(decoration)來填充區域,接着繪製子部件,最後繪製前景裝飾(foregroundDecoration),同時填充該區域。
decoration和foregroundDecoration是填充配置,前者是在子部件之下,後者是子部件之上,能夠設置填充顏色,邊框,填充形狀,陰影,漸變色,背景圖片等。
若是Container的約束是有限制的,那麼沒有子部件的Container會嘗試儘量大,若是Container的約束是沒有限制的(unbounded),它就會盡量小。
有子部件的Container,根據子部件肯定本身的大小。
到底什麼是有限制約束和無限制約束呢,各類部件又都是哪一種約束呢?
在flutter中,widgets由底層的RenderBox渲染盒渲染,父組件向渲染盒提供約束條件,而後渲染盒用這些約束調整本身的尺寸,約束(Constraint)由最大和最小的寬高組成,尺寸(Size)由特定的寬高組成。
一般來講,有三種處理約束的盒子:
但約束有時會變得緊湊,意思是它沒有留給渲染盒子自行決定尺寸的餘地(例如最大寬度和最小寬度相等,那容許的寬度是個固定值),例如App這個Widget,它的約束被設置爲固定的應用程序內容大小(也就是整個屏幕)。而在Flutter中,不少的widget,尤爲是隻能有一個子部件的widget,會傳遞本身的約束到子部件。也就是說,若是你在App根渲染樹裏嵌套了一系列widget,他們將會由於緊湊的約束,一級級地貼着。
可是有些widget會使約束寬鬆,意思是最大的約束保留,可是最小的約束移除了,好比Center。
須要指出的是,ListView會在其交叉方向擴張到父部件邊界,例如一個縱向滾動的列表,在橫向會盡可能和父部件同樣寬。 當你在橫向滾動列表裏,嵌入一個縱向滾動列表的時候,縱向列表會盡量寬,也就是無限寬,由於橫向列表是無盡寬的,這就會異常。
另外,彈性盒子(Row和Column)在有限制和無限制約束的狀況下,表現出來的行爲也不一樣。
由於Container集合了其餘部件的功能,因此它的佈局有些複雜,簡而言之,按照順序,Container會:
maxWidth | maxHeight | 約束 | 有無子組件 | 佈局規則 |
---|---|---|---|---|
有值 | 有值 | 有限制 | 無 | 儘量大 |
有值 | 無值 | 高度無限制,寬度有限制 | 無 | 高度儘量小,寬度儘量大 |
無值 | 有值 | 高度有限制,寬度無限制 | 無 | 高度儘量大,寬度儘量小 |
無值 | 無值 | 無限制 | 無 | 儘量小 |
都行 | 都行 | 都行 | 有 | 在知足約束的前提下儘量小 |
沒有子組件,有約束,儘量大↓
沒有子組件,父組件約束最大寬度是屏幕寬度,最大高度是無限,本身的約束最小寬度是100,最小高度是100,則高度儘量小到100,寬度儘量大到屏幕寬度↓
父組件最大約束是屏幕寬高,本身是固定寬度100,則寬度是100,高度儘量大到屏幕高度↓
本身沒有設置約束,有子組件,因此本身包住子組件↓
本身設置固定高度100,寬度沒有約束,有子組件,則高度爲100,寬度包住子組件↓
有子組件,本身的高度是固定100,寬度設置爲無限,則高度爲100,寬度是父組件的約束屏幕寬度↓
有子組件,設置最小寬高爲無限,則大小爲屏幕大小↓Container應該是flutter中最靈活的佈局widget,你們必定要善用Container,用巧妙的方式處理佈局,不然可能會讓代碼可讀性變差,難以維護