前言:
這是我參與8月更文挑戰的第 23 天,活動詳情檢視:8月更文挑戰。為應掘金的八月更文挑戰
,我準備在本月挑選 31
個以前沒有介紹過的元件,進行全面分析和屬性介紹。這些文章將來會作為 Flutter 元件集錄
的重要素材。希望可以堅持下去,你的支援將是我最大的動力~
1. 認識 Stack 元件
Stack
是一個經常被用到的元件,我看可以通過它來疊合若干個元件。原始碼中對它的介紹是:
一個將其子部件,相對於盒邊緣進行定位的元件。
複製程式碼
也就是說 Stack
元件擅長的是 定位
元件。下面是 Stack
元件類的定義
和 構造方法
,可以看出它繼承自 MultiChildRenderObjectWidget
。所以可接受一個元件列表。另外還有一些配置引數,在下面將一一介紹 。
2. Stack 元件的簡單使用
如下,通過 Stack
將藍色盒子、紅色盒子和一個圖示疊放在一起。可以看出,預設情況下元件會以 Stack
區域的左上角進行對齊疊放,且會根據列表元素的順序依次疊放。
Stack(
children: <Widget>[
Container( width: 100, height: 100, color: Colors.red ),
Container( width: 60, height: 60, color: Colors.green ),
Icon(Icons.ac_unit,color: Colors.white )
],
);
複製程式碼
textDirection
屬性
根據不同國家的閱讀習慣,給出 textDirection
來確定排布方向。其型別為 TextDirection
列舉,有兩個元素,rtl
代表從右向左,ltr
代表從左向右,我們的閱讀習慣自然是 ltr
。
enum TextDirection {
/// The text flows from right to left (e.g. Arabic, Hebrew).
rtl,
/// The text flows from left to right (e.g., English, French).
ltr,
}
複製程式碼
當把 textDirection
設為 rtl
時,效果如下,會以 Stack
區域的右上角進行對齊疊放。
Stack(
textDirection: TextDirection.rtl,
children: <Widget>[
Container( width: 100, height: 100, color: Colors.red ),
Container( width: 60, height: 60, color: Colors.green ),
Icon(Icons.ac_unit,color: Colors.white )
],
);
複製程式碼
alignment
屬性
alignment
屬性我們應該非常熟悉,它的型別是 AlignmentGeometry
,用於控制對齊方式。比如將 alignment
設定為 Alignment.center
常量,就會在 Stack
中居中排布。
Stack(
alignment: Alignment.center,
children: <Widget>[
Container( width: 100, height: 100, color: Colors.red ),
Container( width: 60, height: 60, color: Colors.green ),
Icon(Icons.ac_unit,color: Colors.white )
],
);
複製程式碼
另外 Alignment
除了八個方位外,可以自己指定對齊方式。之前再 《出神入化的Align》 一文中詳細介紹了 alignment
屬性的用法,這裡不再贅述。比如下面是 Alignment(0.2,0.2)
的效果。
3. Stack 的 fit 屬性
fit
屬性型別為 StackFit
列舉,有如下三個元素。預設情況下是 loose
。
enum StackFit {
loose,
expand,
passthrough,
}
複製程式碼
先看個例子:如下,在 Stack
外層通過 ConstrainedBox
施加一個寬高固定
的約束,毫無疑問 Stack
在被強制約束後,其佔位區域被固定。
ConstrainedBox(
constraints: BoxConstraints.tightFor(width:200,height:150),
child: Stack(
fit: StackFit.loose,
children: <Widget>[
Container(width: 100, height: 100, color: Colors.red),
Container(width: 60, height: 60, color: Colors.green),
Icon(Icons.ac_unit,color: Colors.white,)
],
));
複製程式碼
可以看出,在 StackFit.loose
的情況下,子元件並未受到該固定尺寸的約束,而是以該固定區域為上限的鬆散約束,如下紅色所示。
此時,在 StackFit.expand
的情況下,子元件也會受到一個固定尺寸的強約束。
Container
在該約束下,會變成固定的寬高,即使藍色自身要求是 60*60
。
其實稍微瞄一下 RenderStack
的原始碼我們就能知道 fit
具體的處理邏輯。在 loose
時,會通過 constraints.loosen()
將建立一個鬆散約束,該方法就是將最小寬高設為 0
,最大寬高設為對應最大值
。而 expand
會將自身約束的最大區域最為固定
寬高約束。最後 passthrough
則什麼都不處理,直接將自身約束施加給子節點。
BoxConstraints loosen() {
assert(debugAssertIsValid());
return BoxConstraints(
minWidth: 0.0,
maxWidth: maxWidth,
minHeight: 0.0,
maxHeight: maxHeight,
);
}
複製程式碼
4. Stack 的 overflow 與 clipBehavior 屬性
我們可以清楚地看到 overflow
屬性是一個過時的屬性,而 clipBehavior
就是替代它的。clipBehavior
是什麼我就不多說了,詳見 ClipPath 一文。
那為什麼需要 clipBehavior
進行裁剪呢?通過 Positioned
元件可以對子元件進行精確定位,甚至是負數。如下左邊偏移 -20
,右邊偏移 -10
。預設裁剪行為是 hardEdge
,效果如下:
class StackDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return
Container(
color: Colors.grey.withAlpha(33),
constraints: BoxConstraints.tightFor(width:200,height:150),
child: Stack(
children: <Widget>[
Container(width: 100, height: 100, color: Colors.red),
Positioned(
left: -20,
top: -10,
child: Container(width: 60, height: 60, color: Colors.green)),
Icon(Icons.ac_unit,color: Colors.white,)
],
));
}
}
複製程式碼
當 clipBehavior: Clip.none,
時,不會進行裁剪,出界的就會被顯示出來。注意一點,出界的部分是無法響應點選事件
的。如果需要點選,有其他元件能夠解決。
那 Stack
的使用方式到這裡就介紹完畢,那本文到這裡就結束了,謝謝觀看,明天見~