
Divider 组件大家都很熟悉,就是一根水平的分割线,可以指定高度、粗细、颜色、边距。那这些属性默认是什么,如何统一设置默认值,Divider 组件的源码又是如何实现的呢?本文就来详细介绍一下。

下面是 Divider 组件类的定义和 构造方法,可以看出它继承自 StatelessWidget。有五个可选参数:

先看一下 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,
),
),
);
}
}这些属性的含义都很简单,下面代码是三条分割线。
属性名 | 类型 | 默认值 | 用途 |
|---|---|---|---|
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 实现了。

如果一个应用中需要指定默认的 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(),
],
),
),
);
}
}首先,它是 StatelessWidget,只能依赖于其他组件进行构建,核心逻辑在 build 方法中。

另外注意一下,在构造方法的断言中,四个数字属性都不能为负数。

build 方法也比较简单,首先通过 DividerTheme 获取数据,可以看出如果没有设置主体,默认的高度是 16 逻辑像素。也就是说这时 Divider 本身是有一定的高度占位的。区域尺寸通过 SizedBox 设定,分割线是通过 Container 装饰的底边线完成的。其中 indent 和 endIndent 作用于 margin 属性,本质还是通过 Padding 组件完成的边距。

通过调试可以看出默认 DividerTheme 中的数据属性为 null ,那问题来了 Divider 的默认颜色是什么?

在 createBorderSide 静态方法中,可以看出,如果 DividerTheme 颜色为 null ,会根据 Theme 中的 dividerColor 设置颜色。

那Divider 的使用方式到这里就介绍完毕,那本文到这里就结束了,谢谢观看,明天见~