最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

animation - how to make custom circular progress indicator in flutter - Stack Overflow

programmeradmin1浏览0评论

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

[1]: .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.

[![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.

Share Improve this question asked Feb 6 at 2:03 prabin maharjanprabin maharjan 8671 gold badge8 silver badges15 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 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;
}
发布评论

评论列表(0)

  1. 暂无评论