fluttergaugeflutter-custompainter

How to Ensure Full Gradient Coverage in a Rounded StrokeCap Arc in Flutter?


I'm working on a Flutter project where I'm drawing a half-circle gauge with a gradient that transitions from red to yellow to green, using a SweepGradient. The arc looks great overall, but I've encountered an issue where the gradient doesn't fully cover the end of the arc.

gauge image

As shown in the image above, the green color does not fully reach the end of the arc. The stroke cap is set to StrokeCap.round, which is necessary for my design, but it seems to be causing the gradient to stop short of fully reaching the green color at the end of the arc.

Here’s a code to replicate:

import 'dart:math';

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('Custom Gauge Example')),
        body: const Center(
          child: CustomPaint(
            size: Size(200, 100),
            painter: GaugePainter(),
          ),
        ),
      ),
    );
  }
}

class GaugePainter extends CustomPainter {
  const GaugePainter();

  @override
  void paint(Canvas canvas, Size size) {
    const strokeWidth = 16.0;

    final rect = Rect.fromLTWH(
      strokeWidth / 2,
      strokeWidth / 2,
      size.width - strokeWidth,
      size.height * 2 - strokeWidth * 2,
    );

    const gradient = SweepGradient(
      startAngle: pi,
      endAngle: pi * 2,
      colors: [Colors.red, Colors.yellow, Colors.green],
    );

    final gradientShader = gradient.createShader(rect);

    canvas.drawArc(
      rect,
      -pi,
      pi,
      false,
      Paint()
        ..shader = gradientShader
        ..style = PaintingStyle.stroke
        ..strokeCap = StrokeCap.round
        ..strokeWidth = strokeWidth,
    );
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return false;
  }
}

How can I ensure that the gradient fully covers the end of the arc, so the green color is properly displayed, while still maintaining the rounded stroke caps? Any guidance or suggestions would be greatly appreciated!


Solution

  • Try This:

     const gradient = SweepGradient(
              startAngle: 0,
              endAngle: pi * 2,
              colors: [Colors.green,Colors.red,Colors.red, Colors.yellow, Colors.green],
            );