Search code examples
fluttercustom-paintingcustom-painterflutter-custompainterflutter-custompaint

How to skip spaces with CustomPaint with Flutter?


I'm trying to achive an ARC in flutter, but with "holes" in it.

What I have: screen image

What I want: achive image

My code:

class ProgressArc extends CustomPainter {
 bool isBackground;
  Color progressColor;
  double arcLength;
  ProgressArc({
    Key? key,
    required this.isBackground,
    required this.progressColor,
    required this.arcLength,
  });

  @override
  void paint(Canvas canvas, Size size) {
    final rect = Rect.fromLTRB(0, 0, 300, 300);
    final startAngle = -math.pi;
    final sweepAngle = arcLength;
    final useCenter = false;
    final paint = Paint()
      ..strokeCap = StrokeCap.round
      ..color = progressColor
      ..style = PaintingStyle.stroke
      ..strokeWidth = 20;

    var arc = canvas.drawArc(
      rect,
      startAngle,
      sweepAngle,
      useCenter,
      paint,
    );
    return arc;
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    // TODO: implement shouldRepaint
    throw UnimplementedError();
  }
}

Do you guys know what should I do? I'm trying with CustomPaint, but accepting other approaches I need this for a chart, chart libraries do not support this chart that i need.


Solution

  • Hope this can still help you.

    Below is the painter class:

    class ProgressArc extends CustomPainter {
      bool isBackground;
      Color progressColor;
      double arcLength;
      int dynamicPoint;
      double gapSize;
    
      ProgressArc({
        Key? key,
        required this.isBackground,
        required this.progressColor,
        required this.arcLength,
        required this.dynamicPoint,
        required this.gapSize
      });
    
      @override
      void paint(Canvas canvas, Size size) {
        const rect = Rect.fromLTRB(0, 0, 300, 300);
        final double gap = arcLength / 180 * gapSize;
        final double angle = arcLength / dynamicPoint;
    
        final Paint paint = Paint()
            ..color = progressColor
            ..strokeWidth = 20
            ..strokeCap = StrokeCap.round
            ..style = PaintingStyle.stroke;
    
        for (int i = 0; i < dynamicPoint; i++) {
          canvas.drawArc(
            rect,
            -(gap + angle * i), // remove "-" of startAngle and sweepAngle to draw bottom half circle instead of top half
            -(angle - gap * 2),
            false,
            paint);
        }
      }
    
      @override
      bool shouldRepaint(covariant CustomPainter oldDelegate) {
        // TODO: implement shouldRepaint
        throw UnimplementedError();
      }
    }
    

    And to use it, I add dynamicPoint for number of dashes, and gapSize, for the gap between 2 dashes:

    CustomPaint(painter: ProgressArc(
      isBackground: true,
      progressColor: Colors.black,
      arcLength: pi,
      dynamicPoint: 4,
      gapSize: 5.0
    ))