Lucas Paz
Lucas Paz

Reputation: 815

Circle Progress Gradient Border in Flutter

I've been trying to do this for hours and I'm not succeeding at all.

Does anyone have an idea how to do this?

Created by Designer:

Created by designer

Created by me:

Created by me


How is my code:

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

  @override
  Widget build(BuildContext context) {
    return Container(
      width: 55,
      height: 55,
      decoration: BoxDecoration(
        shape: BoxShape.circle,
        boxShadow: [
          BoxShadow(
            color: const Color(0xFF8BC26A).withOpacity(0.3),
            blurRadius: 18.94,
          ),
          BoxShadow(
            color: const Color(0xFF54A99A).withOpacity(0.3),
            blurRadius: 18.94,
          )
        ],
        gradient: const LinearGradient(
          colors: [
            Color(0xFF8BC26A),
            Color(0xFF54A99A)
          ],
          begin: Alignment.centerLeft
        ),
      ),
      child: Container(
        margin: const EdgeInsets.all(4.0),
        decoration: const BoxDecoration(
          color: Colors.black,
          shape: BoxShape.circle
        ),
        child: Image.asset('images/user.png'),
      ),
    );
  }
}

I wanted this gradient to grow as a percentage of progress.

Upvotes: 1

Views: 2039

Answers (1)

Md. Yeasin Sheikh
Md. Yeasin Sheikh

Reputation: 63594

I am using CustomPainter to draw on UI, you can adjust gradient, I'm having some trouble with it. And you can duplicate the widget with Stack with opacity for glow effect.

Run on dartPad.

enter image description here

SizedBox(
  width: 200,
  height: 200,
  child: CustomPaint(
    size: const Size(200, 200), // no effect while adding child
    painter: CircularPaint(
      progressValue: sliderValue, //[0-1]
    ),
    child: const Center(
      child: Icon(
        Icons.umbrella,
        size: 56,
        color: Colors.white,
      ),
    ),
  ),
)

Paint class

import 'dart:math' as math;
///....
double deg2rad(double deg) => deg * math.pi / 180;

class CircularPaint extends CustomPainter {
  /// ring/border thickness, default  it will be 8px [borderThickness].
  final double borderThickness;
  final double progressValue;

  CircularPaint({
    this.borderThickness = 8.0,
    required this.progressValue,
  });
  @override
  void paint(Canvas canvas, Size size) {
    Offset center = Offset(size.width / 2, size.height / 2);

    final rect =
        Rect.fromCenter(center: center, width: size.width, height: size.height);

    Paint paint = Paint()
      ..color = Colors.grey.withOpacity(.3)
      ..style = PaintingStyle.stroke
      ..strokeCap = StrokeCap.round
      ..strokeWidth = borderThickness;

    //grey background
    canvas.drawArc(
      rect,
      deg2rad(0),
      deg2rad(360),
      false,
      paint,
    );

    Paint progressBarPaint = Paint()
      ..style = PaintingStyle.stroke
      ..strokeCap = StrokeCap.round
      ..strokeWidth = borderThickness
      ..shader = const LinearGradient(
        begin: Alignment.centerLeft,
        end: Alignment.centerRight,
        colors: [
          Colors.purple,
          Colors.orange,
          Colors.green,
          Colors.deepOrange,
        ],
      ).createShader(rect);
    canvas.drawArc(
      rect,
      deg2rad(-90),
      deg2rad(360 * progressValue),
      false,
      progressBarPaint,
    );
  }

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

Upvotes: 1

Related Questions