Custom timer widget in flutter with gradient colors to border and timer at the center of the circle

74 Views Asked by At

I want to create a custom timer widget in flutter. The timer should be at the center of the circle and the border of the circle should decrease as the timer decreases. Their should be a circular spot at the end of the border form where it is reducing. I want to apply gradient colors to the border of the circle.

I tried it using Circular progress indicator of flutter but I can't change the color of border to gradient and I can't put the spot at the reducing edge of the circle.

2

There are 2 best solutions below

0
zaid Chauhan On

It seems like you're looking for a custom timer widget in Flutter using the percent_indicator package with gradient colors for the border and a timer at the Center of the circle. Here's a formatted and slightly improved version of the provided example:

CircularPercentIndicator(
  radius: screenWidth / 4,
  lineWidth: 5.0,
  percent: 0.75,
  center: Text(
    "75%",
    style: TextStyle(color: Color(0xFF535355)),
  ),
  linearGradient: LinearGradient(
    begin: Alignment.topRight,
    end: Alignment.bottomLeft,
    colors: <Color>[Color(0xFF1AB600), Color(0xFF6DD400)],
  ),
  rotateLinearGradient: true,
  circularStrokeCap: CircularStrokeCap.round,
)

Add Your Timer Text Into Text Widget And Percent Field In Widget.

0
Mayur Patel On

Please check this code snippet

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

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

    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
         home: Scaffold(
            appBar: AppBar(
             title: const Text('Custom Timer     Widget'),
            ),
            body: const Center(
          child: CustomTimerWidget(
            duration: Duration(seconds: 10),
          ),
        ),
      ),
    );
     }
    }

    class CustomTimerWidget extends StatefulWidget {
    final Duration duration;

    const CustomTimerWidget({required this.duration});

    @override
    _CustomTimerWidgetState createState() => _CustomTimerWidgetState();
    }

    class _CustomTimerWidgetState extends State<CustomTimerWidget>
    with TickerProviderStateMixin {
      late AnimationController _controller;
      late Animation<double> _animation;

      @override
      void initState() {
      super.initState();
      _controller = AnimationController(
      vsync: this,
      duration: widget.duration,
      )..forward();

      _animation = Tween<double>(begin: 0.0, end: 1.0).animate(_controller);
     }

     @override
      Widget build(BuildContext context) {
        return AnimatedBuilder(
      animation: _animation,
      builder: (context, child) {
            return Container(
          width: 200,
          height: 200,
          child: CustomPaint(
            painter: TimerPainter(progress: _animation.value),
            child: Center(
              child: Text(
                '${(_animation.value * widget.duration.inSeconds).ceil()}s',
                style: TextStyle(fontSize: 20.0, color: Colors.black),
              ),
            ),
          ),
        );
      },
      );
    }

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

    class TimerPainter extends CustomPainter {
    final double progress;

    TimerPainter({required this.progress});

    @override
      void paint(Canvas canvas, Size size) {
    final double strokeWidth = 10.0;
    final double radius = (size.shortestSide - strokeWidth) / 2;

    Paint outerCircle = Paint()
      ..strokeWidth = strokeWidth
      ..color = Colors.grey[300]!
      ..style = PaintingStyle.stroke;

    Paint gradientCircle = Paint()
      ..strokeWidth = strokeWidth
      ..shader = LinearGradient(
        colors: [Colors.blue, Colors.red],
      ).createShader(Rect.fromCircle(
          center: Offset(size.width / 2, size.height / 2), radius: radius))
      ..style = PaintingStyle.stroke;

    Paint spotPaint = Paint()
      ..color = Colors.black
      ..strokeWidth = 2.0
      ..style = PaintingStyle.fill;

    canvas.drawCircle(
        Offset(size.width / 2, size.height / 2), radius, outerCircle);
    canvas.drawArc(
      Rect.fromCircle(
          center: Offset(size.width / 2, size.height / 2), radius: radius),
      -pi / 2,
      pi * 2 * progress,
      false,
      gradientCircle,
    );

    // Draw a circular spot at the end of the border
    double spotX = size.width / 2 + radius * cos(pi * 2 * progress - pi / 2);
    double spotY = size.height / 2 + radius * sin(pi * 2 * progress - pi / 2);
    canvas.drawCircle(Offset(spotX, spotY), strokeWidth / 2, spotPaint);
  }

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