1. Flex
如果你不確定需要具體的排列方向是水平還是垂直的時候,可以使用。(可以動態的根據不同的方向具體顯示?)他表示子節點會在一維方向上顯示。
Flex 允許你根據子節點的放置(水平或垂直)來控制軸。這被稱作主軸。你如果事先直到具體的主軸,那么考慮使用Row
或者Column
,因為這不這么冗余。
如果需要讓孩子展開填充可用的垂直空間,用Expanded
包裹孩子。
實際上 Column
和Row
都是繼承 Flex
,并且實現了具體的差異化。
2. Expanded
Expanded
可以展開Row
,Column
,或者Flex
的子結點。
使用Expanded
可以讓Row
,Column
或Flex
的子節點展開來填充其主軸上的剩余可用空間(例如 Row
的水平空間,Column
的垂直空間)。如果多個子結點都被展開,則根據flex
因子來分配的具體空間。
Expanded
控件必須是Row
,Column
或Flex
的后代,從控件到其封閉的Row
,Column
或Flex
的路徑必須只包含StatelessWidget
s 或StatefulWidget
這些,不能是其他類型的Widget(例如RenderObjectWidget
)。
3. Flexible
用于控制
Row
,Column
,Flex
的伸縮值。
實際上Expanded
是繼承 Flexible
。使用Flexible
小部件為Row
、Column
或Flex
的子部件提供了擴展以填充主軸中可用空間的靈活性(例如,水平地填充Row
或垂直地填充Column
),但與Expanded
不同,Flexible
不要求子部件填充可用空間。
Flexible
控件必須是Row
,Column
或Flex
的后代,從控件到其封閉的Row
,Column
或Flex
的路徑必須只包含StatelessWidget
s 或StatefulWidget
這些,不能是其他類型的Widget(例如RenderObjectWidget
)。
4. SingleChildScrollView
一個可以滾動單個widget的框
只容納一個widget,當空間大小不夠的時候,里面的widget可以在主軸上滾動。
你如果需要在兩個方向上收縮包裝(在滾動軸和橫軸)例如 dialog或者 pop-up菜單,在這種情況下,你可以用SingleChildScrollView
包裹孩子ListBody
。
當您有一個子列表并且不需要跨軸收縮包裝行為時,例如,一個始終是屏幕寬度的滾動列表,請考慮ListView,它比包含多個子列表體的ListBody或Column的SingleChildScrollView的效率要高得多。
簡單的代碼:使用一個 Column
的SingleChildScrollView
有時候,布局是圍繞Column的靈活屬性設計的,但是有些時候可能沒有足夠的空間來查看整個內容。這可能是因為一些設備具有異常小的屏幕,或者因為應用程序可以在縱橫比不是最初設想的橫向模式下使用,或者因為應用程序在分割屏幕模式下在小窗口中顯示。無論如何,在singleChildScrollView中包裝布局可能是有意義的。
然而,僅僅這樣做通常會導致Column與SingleChildScrollView之間的沖突,Column通常試圖盡可能地變大,而SingleChildScrollView為子視圖提供了無限大的空間。
為了解決這個明顯的沖突,有一些技術,如下所討論的。這些技術應該只在通常期望內容適合屏幕時才使用,這樣基于sliver的ListView或CustomScrollView的惰性實例化就不會提供任何性能優勢。如果預期視口通常包含超出屏幕尺寸的內容,那么SingleChildScrollView將非常昂貴。
居中、間隔或對齊固定高度的內容
如果內容具有固定的(或內在的)維度,但是需要使用列的Flex布局模型進行分隔、居中或其他定位,那么可以使用以下技術向列提供最小維度,同時允許它在沒有時收縮包裝內容足夠的空間來應用這些間距或對齊需要。
LayoutBuilder用于獲得視口的大小(隱式地通過SingleChildScrollView看到的約束,因為視口通常增長以適應其最大高度約束)。然后,在滾動視圖中,使用ConstrainedBox來設置Column的最小高度。
Column沒有展開的子元素,因此它不是從BoxConstraints.maxHeight獲取無限的高度(viewport不提供最大高度約束),而是自動嘗試收縮以適合其子元素。但是,它不能小于其BoxConstraints.minHeight,因此它變為ConstrainedBox提供的最小高度和子節點高度的總和。
如果子節點不足以適應最小大小,那么Column最終將得到一些剩余空間來分配,這是由Column.mainAxisAlignment參數指定的。
body: new LayoutBuilder(
builder: (BuildContext context, BoxConstraints viewportConstraints) {
return new SingleChildScrollView(
child: new ConstrainedBox(
constraints:
new BoxConstraints(minHeight: viewportConstraints.maxHeight),
child: new Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
new Container(
color: Colors.yellow,
height: 120.0,
),
new Container(
color: Colors.red,
height: 200.0,
)
],
),
),
);
}),
在這個例子中,子結點被平均地間隔開來,除非沒有更多的空間;在沒有更多空間情況下,他們垂直堆疊并滾動。
當使用這種技術時,Expanded和Flexible是沒有用的,因為在這兩種情況下,“可用空間”都是無限的(因為這在視口中)。下一節描述了一種提供最大高度約束的技術。
展開內容以適應可視區域
下面的示例建立在前一個示例上。除了為子列提供最小維度之外,還使用IntrinsicHeight小部件強制列與其內容一樣大。這個約束與前面討論的ConstrainedBox約束相結合,以確保該列要么與viewport一樣大,要么與內容一樣大,無論哪個最大。
必須使用這兩個約束來獲得期望的效果。如果只指定了IntrinsicHeight,那么當其子視圖小于整個屏幕時,該列就不會增長到適合整個視圖。如果僅使用視口的大小,則如果兒童大于視口,則列將溢出。
///LayoutBuilder +SingleChildScrollView+IntrinsicHeight+Expanded
body: new LayoutBuilder(
builder: (BuildContext cotext, BoxConstraints viewportConstraints) {
return SingleChildScrollView(
child: new ConstrainedBox(
constraints:
new BoxConstraints(minHeight: viewportConstraints.maxHeight),
child: new IntrinsicHeight(
child: new Column(
children: <Widget>[
new Container(
color: Colors.yellow,
height: 120.0,
),
new Expanded(
child: new Container(
color: Colors.red,
height: 50.0,
))
],
),
),
),
);
}),
這種技術相當昂貴,因為它或多或少要求對視口的內容進行兩次布局(一次找到它們的內在尺寸,一次實際布局它們)。因此,列中的小部件的數量應該保持較小。或者,具有已知維度的子集可以封裝在具有緊密垂直約束的SiezedBox中,以便當內部大小調整算法到達子樹的那些部分時可以縮短計算。
所以可以看看其他的控件
- ListVIEW,它處理滾動列表中的多個子項。
- GRIDVIEW,它處理滾動網格中的多個子類。
- PageView,一個可滾動的,一頁一頁地工作。
- Scrollable,處理任意滾動效果。