这一篇是用来记录学习过程中遇到的一些可以用来组件化的Widget,记录下来方便以后的使用。

虚线 dash line

在平时的前端开发的时候,需要用到虚线的时候我都会用dashed border来做,非常的方便,没想到Flutter的border属性没有dashed这个选项,只有solid和none,所以只能想别的方法了,我找到了以下两个方法来实现虚线。

dash line widget

这个做法是根据需要的高度,计算出虚线需要多少根实线组成,实线还是用solid border来做,然后将这些实现均匀的排列在一条线上,就形成了虚线的形状。
代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import 'package:flutter/material.dart';

class VerticalDashLine extends StatelessWidget {
final Color color;

const VerticalDashLine({this.color = Colors.black});

@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
final height = constraints.constrainHeight();
final dashWidth = 4.0;
final dashCount = (height / (2 * dashWidth)).floor();

return Flex(
children: List.generate(dashCount, (_) {
return SizedBox(
width: 1,
height: dashWidth,
child: DecoratedBox(
decoration: BoxDecoration(color: color),
),
);
}),
mainAxisAlignment: MainAxisAlignment.spaceBetween,
direction: Axis.vertical,
);
},
);
}
}

上面的示例是实现一个垂直方向的虚线,如果需要横向的也同理。
这个做法的优点是比较方便,需要用到的时候直接调用即可,但是是通过很多小实现来拼接成一整条虚线,总感觉不是很优雅,如果需要一条很长的虚线,也不知道这么多SizedBox会不会有性能问题。

ShapeBorder

这个做法是继承Flutter源码里用来渲染border的方法,ShapeBorder可以画出任何你想要的图形,这里我只贴出画虚线的方法,其他的需求以后用到了再贴出来。
代码如下
首先继承方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import 'package:flutter/material.dart';

class CustomShapeBorder extends ShapeBorder {
// 这里可以用来传递参数,虚线的颜色、宽度等等
CustomShapeBorder();

@override
EdgeInsetsGeometry get dimensions => null;

@override
Path getInnerPath(Rect rect, {TextDirection textDirection}) {
return null;
}

@override
Path getOuterPath(Rect rect, {TextDirection textDirection}) {
return null;
}

@override
void paint(Canvas canvas, Rect rect, {TextDirection textDirection}) {
var paint = Paint();
// 用级联操作符来更改虚线的属性,可以省略 [级联操作符的用法](https://blog.vampuck.com/2020/05/02/flutter-dart/)
..color = Colors.white // 虚线的颜色
..strokeWidth = 1 // 虚线的宽度
_drawDashLine(canvas, Offset(rect.width - 100, 0), rect.height / 16,
rect.height, paint);
}

/**
* 传入所需参数
* @param start 虚线所处的位置,我这里用的是距离,即从距离容器右侧100,顶部0的位置开始绘制,也可以用百分比
* @param count 虚线的个数,我这里每个虚线加空白的长度用的是16,用来修改虚线的密集程度
* @param height 虚线的总长度,这里我用的是容器的高度
*/
_drawDashLine(
Canvas canvas, Offset start, double count, double length, Paint paint) {
var step = length / count / 2;
for (int i = 0; i < count; i++) {
var offset = start + Offset(0, 2 * step * i + 7);
// 每隔一段空白画一段实线
canvas.drawLine(offset, offset + Offset(0, step), paint);
}
}

@override
ShapeBorder scale(double t) {
return null;
}
}

然后再应用自己写的ShapeBorder

1
2
3
4
Material(
shape: CustomShapeBorder(),
child: // ...
)

这样在你的Material Widget的距离右侧100的位置就出现了一根虚线
效果如图
example

参考

  1. https://blog.csdn.net/mubowen666/article/details/104709246/