title: how to make Percent Indicator change color programmatically in flutter?
body: <p>I'm using a package called percent indicator <a href="https://pub.dev/packages/percent_indicator" rel="nofollow noreferrer">https://pub.dev/packages/percent_indicator</a></p>
  
  <p>and I'm currently using its CircularPercentIndicator()</p>
  
  <p>I'm just wondering how to change the progress color when a certain percentage met?</p>
  
  <p>For example: I have a starting progress color of green at 0% when reaching 60% progress color should change to orange and when reaching 80% color should be red.</p>
  
  <p>here's what I got at the moment:</p>
  
  <pre><code>import 'package:flutter/material.dart';
  import 'package:percent_indicator/circular_percent_indicator.dart';
  
  class RoutinePage extends StatefulWidget {
    @override
    _RoutinePageState createState() =&gt; _RoutinePageState();
  }
  
  class _RoutinePageState extends State&lt;RoutinePage&gt; {
    double progress = 0;
  
    @override
    Widget build(BuildContext context) {
      return Stack(
        children: &lt;Widget&gt;[
          Container(
            color: Colors.white,
            alignment: Alignment(0, 0),
            child: CircularPercentIndicator(
              animationDuration: 100,
              animateFromLastPercent: true,
              arcType: ArcType.FULL,
              arcBackgroundColor: Colors.black12,
              backgroundColor: Colors.white,
              progressColor: Colors.green,
              percent: progress,
              animation: true,
              radius: 250.0,
              lineWidth: 12.0,
              circularStrokeCap: CircularStrokeCap.round,
            ),
          ),
          Container(
            alignment: Alignment(0, 0),
            child: Text("${this.progress * 100}%",
              style: TextStyle(
                fontSize: 30,
                fontWeight: FontWeight.bold,
              ),
            ),
          ),
          Container(
            alignment: Alignment(0.3, 0.5),
            child: RaisedButton(
                color: Colors.green,
                 onPressed: () {
                  final updated = ((this.progress + 0.1).clamp(0.0, 1.0) * 100);
                  setState(() {
                    this.progress = updated.round() / 100;
                  });
                  print(progress);
                },
                child: Text('+10%',
                style: TextStyle(
                  fontWeight: FontWeight.bold,
                  color: Colors.white,
                ),)),
          ),
          Container(
            alignment: Alignment(-0.3, 0.5),
            child: RaisedButton(
                color: Colors.red,
                onPressed: () {
                  final updated = ((this.progress - 0.1).clamp(0.0, 1.0) * 100);
                  setState(() {
                    this.progress = updated.round() / 100;
                  });
                  print(progress);
                },
                child: Text('-10%',
                style: TextStyle(
                  fontWeight: FontWeight.bold,
                  color: Colors.white,
                ),)),
          ),
        ],
      );
    }
  }
  </code></pre>
  
  <p>and I don't know if this will help but this is the code of CircularPercentIndicator()</p>
  
  <pre><code>//import 'dart:math';
  
  import 'package:flutter/material.dart';
  import 'package:vector_math/vector_math_64.dart' as math;
  
  enum CircularStrokeCap { butt, round, square }
  
  enum ArcType {
    HALF,
    FULL,
  }
  
  class CircularPercentIndicator extends StatefulWidget {
    ///Percent value between 0.0 and 1.0
    final double percent;
    final double radius;
  
    ///Width of the line of the Circle
    final double lineWidth;
  
    ///Color of the background of the circle , default = transparent
    final Color fillColor;
  
    ///First color applied to the complete circle
    final Color backgroundColor;
  
    Color get progressColor =&gt; _progressColor;
  
    Color _progressColor;
  
    ///true if you want the circle to have animation
    final bool animation;
  
    ///duration of the animation in milliseconds, It only applies if animation attribute is true
    final int animationDuration;
  
    ///widget at the top of the circle
    final Widget header;
  
    ///widget at the bottom of the circle
    final Widget footer;
  
    ///widget inside the circle
    final Widget center;
  
    final LinearGradient linearGradient;
  
    ///The kind of finish to place on the end of lines drawn, values supported: butt, round, square
    final CircularStrokeCap circularStrokeCap;
  
    ///the angle which the circle will start the progress (in degrees, eg: 0.0, 45.0, 90.0)
    final double startAngle;
  
    /// set true if you want to animate the linear from the last percent value you set
    final bool animateFromLastPercent;
  
    /// set false if you don't want to preserve the state of the widget
    final bool addAutomaticKeepAlive;
  
    /// set the arc type
    final ArcType arcType;
  
    /// set a circular background color when use the arcType property
    final Color arcBackgroundColor;
  
    /// set true when you want to display the progress in reverse mode
    final bool reverse;
  
    /// Creates a mask filter that takes the progress shape being drawn and blurs it.
    final MaskFilter maskFilter;
  
    CircularPercentIndicator(
        {Key key,
        this.percent = 0.0,
        this.lineWidth = 5.0,
        this.startAngle = 0.0,
        @required this.radius,
        this.fillColor = Colors.transparent,
        this.backgroundColor = const Color(0xFFB8C7CB),
        Color progressColor,
        this.linearGradient,
        this.animation = false,
        this.animationDuration = 500,
        this.header,
        this.footer,
        this.center,
        this.addAutomaticKeepAlive = true,
        this.circularStrokeCap,
        this.arcBackgroundColor,
        this.arcType,
        this.animateFromLastPercent = false,
        this.reverse = false,
        this.maskFilter})
        : super(key: key) {
      if (linearGradient != null &amp;&amp; progressColor != null) {
        throw ArgumentError(
            'Cannot provide both linearGradient and progressColor');
      }
      _progressColor = progressColor ?? Colors.red;
  
      assert(startAngle &gt;= 0.0);
      if (percent &lt; 0.0 || percent &gt; 1.0) {
        throw Exception("Percent value must be a double between 0.0 and 1.0");
      }
  
      if (arcType == null &amp;&amp; arcBackgroundColor != null) {
        throw ArgumentError('arcType is required when you arcBackgroundColor');
      }
    }
  
    @override
    _CircularPercentIndicatorState createState() =&gt;
        _CircularPercentIndicatorState();
  }
  
  class _CircularPercentIndicatorState extends State&lt;CircularPercentIndicator&gt;
      with SingleTickerProviderStateMixin, AutomaticKeepAliveClientMixin {
    AnimationController _animationController;
    Animation _animation;
    double _percent = 0.0;
  
    @override
    void dispose() {
      if (_animationController != null) {
        _animationController.dispose();
      }
      super.dispose();
    }
  
    @override
    void initState() {
      if (widget.animation) {
        _animationController = AnimationController(
            vsync: this,
            duration: Duration(milliseconds: widget.animationDuration));
        _animation =
            Tween(begin: 0.0, end: widget.percent).animate(_animationController)
              ..addListener(() {
                setState(() {
                  _percent = _animation.value;
                });
              });
        _animationController.forward();
      } else {
        _updateProgress();
      }
      super.initState();
    }
  
    @override
    void didUpdateWidget(CircularPercentIndicator oldWidget) {
      super.didUpdateWidget(oldWidget);
      if (oldWidget.percent != widget.percent ||
          oldWidget.startAngle != widget.startAngle) {
        if (_animationController != null) {
          _animationController.duration =
              Duration(milliseconds: widget.animationDuration);
          _animation = Tween(
                  begin: widget.animateFromLastPercent ? oldWidget.percent : 0.0,
                  end: widget.percent)
              .animate(_animationController);
          _animationController.forward(from: 0.0);
        } else {
          _updateProgress();
        }
      }
    }
  
    _updateProgress() {
      setState(() {
        _percent = widget.percent;
      });
    }
  
    @override
    Widget build(BuildContext context) {
      super.build(context);
      var items = List&lt;Widget&gt;();
      if (widget.header != null) {
        items.add(widget.header);
      }
      items.add(Container(
          height: widget.radius + widget.lineWidth,
          width: widget.radius,
          child: CustomPaint(
            painter: CirclePainter(
                progress: _percent * 360,
                progressColor: widget.progressColor,
                backgroundColor: widget.backgroundColor,
                startAngle: widget.startAngle,
                circularStrokeCap: widget.circularStrokeCap,
                radius: (widget.radius / 2) - widget.lineWidth / 2,
                lineWidth: widget.lineWidth,
                arcBackgroundColor: widget.arcBackgroundColor,
                arcType: widget.arcType,
                reverse: widget.reverse,
                linearGradient: widget.linearGradient,
                maskFilter: widget.maskFilter),
            child: (widget.center != null)
                ? Center(child: widget.center)
                : Container(),
          )));
  
      if (widget.footer != null) {
        items.add(widget.footer);
      }
  
      return Material(
        color: widget.fillColor,
        child: Container(
            child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          mainAxisSize: MainAxisSize.min,
          children: items,
        )),
      );
    }
  
    @override
    bool get wantKeepAlive =&gt; widget.addAutomaticKeepAlive;
  }
  
  class CirclePainter extends CustomPainter {
    final Paint _paintBackground = Paint();
    final Paint _paintLine = Paint();
    final Paint _paintBackgroundStartAngle = Paint();
    final double lineWidth;
    final double progress;
    final double radius;
    final Color progressColor;
    final Color backgroundColor;
    final CircularStrokeCap circularStrokeCap;
    final double startAngle;
    final LinearGradient linearGradient;
    final Color arcBackgroundColor;
    final ArcType arcType;
    final bool reverse;
    final MaskFilter maskFilter;
  
    CirclePainter(
        {this.lineWidth,
        this.progress,
        @required this.radius,
        this.progressColor,
        this.backgroundColor,
        this.startAngle = 0.0,
        this.circularStrokeCap = CircularStrokeCap.round,
        this.linearGradient,
        this.reverse,
        this.arcBackgroundColor,
        this.arcType,
        this.maskFilter}) {
      _paintBackground.color = backgroundColor;
      _paintBackground.style = PaintingStyle.stroke;
      _paintBackground.strokeWidth = lineWidth;
  
      if (arcBackgroundColor != null) {
        _paintBackgroundStartAngle.color = arcBackgroundColor;
        _paintBackgroundStartAngle.style = PaintingStyle.stroke;
        _paintBackgroundStartAngle.strokeWidth = lineWidth;
      }
  
      _paintLine.color = progressColor;
      _paintLine.style = PaintingStyle.stroke;
      _paintLine.strokeWidth = lineWidth;
      if (circularStrokeCap == CircularStrokeCap.round) {
        _paintLine.strokeCap = StrokeCap.round;
      } else if (circularStrokeCap == CircularStrokeCap.butt) {
        _paintLine.strokeCap = StrokeCap.butt;
      } else {
        _paintLine.strokeCap = StrokeCap.square;
      }
    }
  
    @override
    void paint(Canvas canvas, Size size) {
      final center = Offset(size.width / 2, size.height / 2);
      canvas.drawCircle(center, radius, _paintBackground);
  
      if (maskFilter != null) {
        _paintLine.maskFilter = maskFilter;
      }
      if (linearGradient != null) {
        /*
        _paintLine.shader = SweepGradient(
                center: FractionalOffset.center,
                startAngle: math.radians(-90.0 + startAngle),
                endAngle: math.radians(progress),
                //tileMode: TileMode.mirror,
                colors: linearGradient.colors)
            .createShader(
          Rect.fromCircle(
            center: center,
            radius: radius,
          ),
        );*/
        _paintLine.shader = linearGradient.createShader(
          Rect.fromCircle(
            center: center,
            radius: radius,
          ),
        );
      }
  
      double fixedStartAngle = startAngle;
  
      double startAngleFixedMargin = 1.0;
      if (arcType != null) {
        if (arcType == ArcType.FULL) {
          fixedStartAngle = 220;
          startAngleFixedMargin = 172 / fixedStartAngle;
        } else {
          fixedStartAngle = 270;
          startAngleFixedMargin = 135 / fixedStartAngle;
        }
      }
  
      if (arcBackgroundColor != null) {
        canvas.drawArc(
          Rect.fromCircle(center: center, radius: radius),
          math.radians(-90.0 + fixedStartAngle),
          math.radians(360 * startAngleFixedMargin),
          false,
          _paintBackgroundStartAngle,
        );
      }
  
      if (reverse) {
        final start =
            math.radians(360 * startAngleFixedMargin - 90.0 + fixedStartAngle);
        final end = math.radians(-progress * startAngleFixedMargin);
        canvas.drawArc(
          Rect.fromCircle(
            center: center,
            radius: radius,
          ),
          start,
          end,
          false,
          _paintLine,
        );
      } else {
        final start = math.radians(-90.0 + fixedStartAngle);
        final end = math.radians(progress * startAngleFixedMargin);
        canvas.drawArc(
          Rect.fromCircle(
            center: center,
            radius: radius,
          ),
          start,
          end,
          false,
          _paintLine,
        );
      }
    }
  
    @override
    bool shouldRepaint(CustomPainter oldDelegate) {
      return true;
    }
  }
  </code></pre>