flutter Canvas绘制进度条

效果展示

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;
}

demo地址

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容