效果展示

L1VzZXJzL2x1d2VuamluZy9MaWJyYXJ5L0FwcGxpY2F0aW9uIFN1cHBvcnQvaURpbmdUYWxrLzM2MjU2MTM3NThfdjIvSW1hZ2VGaWxlcy8xNjk3NTMwMjkwNjYxXzdBQzM5QTM1LTc1NzItNEIwMC05NDY4LTQ3MUVGNDk0NERCRi5wbmc=.png
实现代码
class CustomProgree extends StatelessWidget {
final double progress; //进度
final Color borderColor; //边框颜色 默认 红色
final Color color; //进度条颜色 默认 红色
final double width; //宽 默认 300
const CustomProgree({
Key? key,
this.progress = 0.0,
this.borderColor = Colors.red,
this.color = Colors.red,
this.width = 300,
}) : assert(0 <= progress && progress <= 1, 'progress range 0~1'),
super(key: key);
@override
Widget build(BuildContext context) {
return CustomPaint(
size: Size(width, 20),
foregroundPainter: CustomForegroundPainter(borderColor),
painter: MyPainter(progress, color),
);
}
}
class CustomForegroundPainter extends CustomPainter {
final Color borderColor;
CustomForegroundPainter(this.borderColor);
final Paint _paint = Paint()
..style = PaintingStyle.stroke
..strokeWidth = 1
..isAntiAlias = true;
final double _space = 5;
@override
void paint(Canvas canvas, Size size) {
_paint.color = borderColor;
Rect rect = Offset.zero & size;
canvas.translate(rect.width / 2, rect.height / 2);
canvas.save();
Path path = Path();
path.moveTo(-rect.width / 2, -_space);
path.relativeArcToPoint(Offset(rect.height / 2, -rect.height / 2),
radius: const Radius.circular(10));
path.relativeLineTo(rect.width - rect.height, 0);
path.relativeArcToPoint(Offset(rect.height / 2, rect.height / 2),
radius: const Radius.circular(10));
canvas.drawPath(path, _paint);
canvas.restore();
// 旋转画布 得到下面边框
canvas.transform(Matrix4.rotationZ(180 * pi / 180).storage);
canvas.drawPath(path, _paint);
}
@override
bool shouldRepaint(CustomForegroundPainter oldDelegate) =>
borderColor != oldDelegate.borderColor;
@override
bool shouldRebuildSemantics(CustomForegroundPainter oldDelegate) => false;
}
class MyPainter extends CustomPainter {
final double progress;
final Color color;
MyPainter(this.progress, this.color);
final Paint _paint = Paint()
..style = PaintingStyle.fill
..strokeWidth = 1
..isAntiAlias = true;
final double _spaceH = 10; // 进度条 距离边框左右的 间距
final double _spaceV = 5; // 进度条 距离边框上下的 间距
@override
void paint(Canvas canvas, Size size) {
_paint.color = color;
Rect rect = Offset.zero & size;
double right =
(rect.right - _spaceH) - (size.width - _spaceH * 2) * (1 - progress);
Rect _rect = Rect.fromLTRB(
rect.left + _spaceH, rect.top + _spaceV, right, rect.bottom - _spaceV);
// 进度条 圆角
double _radius = (rect.height - _spaceV * 2) / 2;
canvas.drawRRect(
RRect.fromRectAndRadius(_rect, Radius.circular(_radius)), _paint);
}
@override
bool shouldRepaint(MyPainter oldDelegate) =>
progress != oldDelegate.progress && color != oldDelegate.color;
@override
bool shouldRebuildSemantics(MyPainter oldDelegate) => false;
}