前言:
这是我参与8月更文挑战的第 18 天,活动详情查看:8月更文挑战。为应掘金的八月更文挑战
,我准备在本月挑选 31
个以前没有介绍过的组件,进行全面分析和属性介绍。这些文章将来会作为 Flutter 组件集录
的重要素材。希望可以坚持下去,你的支持将是我最大的动力~
| 本系列 | 组件文章 | 列表 | | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | | 1.NotificationListener | 2.Dismissible | 3.Switch | | 4.Scrollbar | 5.ClipPath | 6.CupertinoActivityIndicator | | 7.Opacity | 8.FadeTransition | 9. AnimatedOpacity | | 10. FadeInImage | 11. Offstage | 12. TickerMode | | 13. Visibility | 14. Padding | 15. AnimatedContainer | | 16.CircleAvatar | 17.PhysicalShape | 18.Divider | | 19.Flexible、Expanded 和 Spacer | 20.Card | |
一、认识 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 之间。
dart 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
指定的高并非一定生效,它会受到父级区域约束的管控。
dart 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 组件不会显示。
dart 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 | 线颜色 |
dart 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
按照默认样式进行展现。效果如下:
dart 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
的使用方式到这里就介绍完毕,那本文到这里就结束了,谢谢观看,明天见~