0

[![enter image description here][1]][1]

[1]: https://i.sstatic.net/bZSXtA7U.png**strong text**

import 'package:flutter/material.dart';
import 'dart:math';

void main() {
  runApp(const MaterialApp(
    debugShowCheckedModeBanner: false,
    home: Scaffold(
      backgroundColor: Colors.white,
      body: Center(child: RotatingCircularProgress()),
    ),
  ));
}

class RotatingCircularProgress extends StatefulWidget {
  const RotatingCircularProgress({super.key});

  @override
  State<RotatingCircularProgress> createState() => _RotatingCircularProgressState();
}

class _RotatingCircularProgressState extends State<RotatingCircularProgress>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      vsync: this,
      duration: const Duration(seconds: 2),
    )..repeat(); // Infinite rotation
  }

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: 100,
      height: 100,
      child: AnimatedBuilder(
        animation: _controller,
        builder: (context, child) {
          return Transform.rotate(
            angle: _controller.value * 2 * pi, // Rotate whole indicator
            child: CustomPaint(
              painter: CircularProgressPainter(),
            ),
          );
        },
      ),
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
}

class CircularProgressPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    final center = size.center(Offset.zero);
    final radius = size.width / 2;
    final strokeWidth = 10.0;
    const startAngle = pi;//-pi / 2; // Start from top
    const sweepAngle = pi*1.7;//1.8 * pi; // ¾ circle

    // Gradient from green (start) to white (end)
    final gradient = SweepGradient(
      colors: [
        Colors.green,                // Start Green
        Colors.green.withOpacity(0.7),
        Colors.green.withOpacity(0.4),
        Colors.green.withOpacity(0.1),
        Colors.white,                // End White
      ],
      stops: const [0.0, 0.3, 0.6, 0.85, 1.0],  // Smooth transition
      tileMode: TileMode.clamp,  // Avoids unwanted repetition
    );

    final paint = Paint()
      ..shader = gradient.createShader(Rect.fromCircle(center: center, radius: radius))
      ..style = PaintingStyle.stroke
      ..strokeWidth = strokeWidth
      ..strokeCap = StrokeCap.round; // Rounded at the start

    // Draw arc
    canvas.drawArc(
      Rect.fromCircle(center: center, radius: radius),
      startAngle,
      sweepAngle,
      false,
      paint,
    );
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}

how to make custom circular progress indicator as in the pic. I've tried multiple ways but i am unable to achieve something like the one in the picture.I am trying to build exactly as in the picture. I'm new to animations. Help or guidance is highly appreciated.

1 Answer 1

2

I just adjusted startAngle and sweepAngle, might achieve what you want

import 'package:flutter/material.dart';
import 'dart:math';

void main() {
  runApp(const MaterialApp(
    debugShowCheckedModeBanner: false,
    home: Scaffold(
      backgroundColor: Colors.white,
      body: Center(child: RotatingCircularProgress()),
    ),
  ));
}

class RotatingCircularProgress extends StatefulWidget {
  const RotatingCircularProgress({super.key});

  @override
  State<RotatingCircularProgress> createState() => _RotatingCircularProgressState();
}

class _RotatingCircularProgressState extends State<RotatingCircularProgress>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      vsync: this,
      duration: const Duration(seconds: 2),
    )..repeat(); // Infinite rotation
  }

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: 100,
      height: 100,
      child: AnimatedBuilder(
        animation: _controller,
        builder: (context, child) {
          return Transform.rotate(
            angle: _controller.value * 2 * pi, // Rotate whole indicator
            child: CustomPaint(
              painter: CircularProgressPainter(),
            ),
          );
        },
      ),
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
}

class CircularProgressPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    final center = size.center(Offset.zero);
    final radius = size.width / 2;
    final strokeWidth = 10.0;
    const startAngle = 0.2;//-pi / 2; // Start from top
    const sweepAngle = pi*1.7 + 0.2;//1.8 * pi; // ¾ circle

    // Gradient from green (start) to white (end)
    final gradient = SweepGradient(
      startAngle: startAngle,
      endAngle: sweepAngle,
      colors: [
        Colors.white,                // End White
        Colors.green,                // Start Green
      ],
      stops: const [0.0, 1.0],  // Smooth transition
      tileMode: TileMode.clamp,  // Avoids unwanted repetition
    );

    final paint = Paint()
      ..shader = gradient.createShader(Rect.fromCircle(center: center, radius: radius))
      ..style = PaintingStyle.stroke
      ..strokeWidth = strokeWidth
      ..strokeCap = StrokeCap.round; // Rounded at the start

    // Draw arc
    canvas.drawArc(
      Rect.fromCircle(center: center, radius: radius),
      startAngle,
      sweepAngle,
      false,
      paint,
    );
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}
1

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.