前言:
這是我參與8月更文挑戰的第 18 天,活動詳情檢視:8月更文挑戰。為應掘金的八月更文挑戰
,我準備在本月挑選 31
個以前沒有介紹過的元件,進行全面分析和屬性介紹。這些文章將來會作為 Flutter 元件集錄
的重要素材。希望可以堅持下去,你的支援將是我最大的動力~
一、認識 Divider 元件
Divider
元件大家都很熟悉,就是一根水平的分割線,可以指定高度、粗細、顏色、邊距。那這些屬性預設是什麼,如何統一設定預設值,Divider
元件的原始碼又是如何實現的呢?本文就來詳細介紹一下。
1. Divider 基本資訊
下面是 Divider
元件類的定義
和 構造方法
,可以看出它繼承自 StatelessWidget
。有五個可選引數:
2.Divider 的尺寸分析
先看一下 Divider
的尺寸特點:下面先通過[w(10,200) - h(0,200)]
的約束。Divider
可以通過 height
指定其尺寸區域高度,而寬度是父級約束的最大值。
注: [w(a,b) - h(c,d)]
表示,尺寸約束寬在 a 和 b 之間,高在 c 和 d 之間。
class DividerDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ConstrainedBox(
constraints: BoxConstraints(
maxWidth: 200,
minWidth: 10,
maxHeight: 200,
minHeight: 0
),
child: Divider(
height: 10,
),
);
}
}
複製程式碼
當約束改為[w(10,200) - h(50,200)]
,可以看出 Divider
指定的高就會無效。也就是說 Divider
指定的高並非一定生效,它會受到父級區域約束的管控。
class DividerDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ConstrainedBox(
constraints: BoxConstraints(
maxWidth: 200,
minWidth: 10,
maxHeight: 200,
minHeight: 50
),
child: Divider(
height: 10,
),
);
}
}
複製程式碼
如果通過 UnconstrainedBox
接觸父級的約束,那麼 Divider
元件由於寬度沒有限制,就不會顯示。這也說明了父級的區域約束對 Divider
元件是很重要的。
通過渲染樹可以看出,Divider 元件對應的渲染物件最終尺寸為 Size(0,0)
,這也就解釋了為什麼在無約束的情況下,Divider 元件不會顯示。
class DividerDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ConstrainedBox(
constraints: BoxConstraints(
maxWidth: 200,
minWidth: 10,
maxHeight: 200,
minHeight: 50
),
child: UnconstrainedBox(
child: Divider(
height: 10,
),
),
);
}
}
複製程式碼
3.Divider 的屬性
這些屬性的含義都很簡單,下面程式碼是三條分割線。
屬性名 | 型別 | 預設值 | 用途 |
---|---|---|---|
height | double | null | 元件高 |
thickness | double | null | 線粗細 |
indent | double | null | 左邊距 |
endIndent | double | null | 右邊距 |
color | Color | null | 線顏色 |
class DividerDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
width: 200,
child: Wrap(
children:[
const Divider(
height: 10,
indent: 20,
endIndent: 20,
thickness: 1,
color: Colors.orange,
),
const Divider(
height: 10,
indent: 10,
endIndent: 10,
thickness: 2,
color: Colors.blueAccent,
),
const Divider(
height: 10,
),
],
),
);
}
}
複製程式碼
其中 indent
和 endIndent
可以用於類似這樣的邊距,就不需要額外套 Padding
實現了。
4.Divider 的預設屬性
如果一個應用中需要指定預設的 Divider
樣式,每次使用都設定一下顯然很麻煩。Flutter 中有相關的主題元件 DividerTheme
,其中維護了 DividerThemeData
資料。我們可以通過 該元件使其子節點的 Divider
按照預設樣式進行展現。效果如下:
class DividerDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return DividerTheme(
data: DividerThemeData(
color: Colors.orange,
thickness: 1/window.devicePixelRatio,
space: 5
),
child: Container(
width: 200,
child: Wrap(
children:[
const Divider(),
const Divider(),
const Divider(),
],
),
),
);
}
}
複製程式碼
二、 Divider 的原始碼實現
首先,它是 StatelessWidget
,只能依賴於其他元件進行構建,核心邏輯在 build
方法中。
另外注意一下,在構造方法的斷言中,四個數字屬性都不能為負數
。
build
方法也比較簡單,首先通過 DividerTheme
獲取資料,可以看出如果沒有設定主體,預設的高度是 16
邏輯畫素。也就是說這時 Divider
本身是有一定的高度佔位的。區域尺寸通過 SizedBox
設定,分割線是通過 Container
裝飾的底邊線完成的。其中 indent
和 endIndent
作用於 margin
屬性,本質還是通過 Padding
元件完成的邊距。
通過除錯可以看出預設 DividerTheme
中的資料屬性為 null
,那問題來了 Divider
的預設顏色是什麼?
在 createBorderSide
靜態方法中,可以看出,如果 DividerTheme
顏色為 null
,會根據 Theme
中的 dividerColor
設定顏色。
那Divider
的使用方式到這裡就介紹完畢,那本文到這裡就結束了,謝謝觀看,明天見~