0

I have an AnimationController, and I want to repeat it every time the animation completes.

Let's say I want it to repeat for 4 times as is shown below:

// ......
// _sets is initialised as 4

    _controller = AnimationController(
        duration: Duration(seconds: _roundDuration), vsync: this);
    _controller.addListener(() {
      if (_controller.isCompleted) {
        _sets--;
        if (_sets > 0) {
          _controller.reset();
          _controller.forward();
        } else {
          _controller.stop();
        }
      }
    });
    super.initState();
  }

The problem is that after repeating this process for 3 times, it becomes very laggy.

The value of the controller is passed to an AnimatedBuilder for driving my CustomPainter-based animation:

 child: AnimatedBuilder(
                        builder: (_, __) {
                          return CustomPaint(
                              painter: MyPainter(
                                  percentValue: _controller.value,
                                  moveDuration: _moveDuration,
                                  holdDuration: _holdDuration));
                        },
                        animation: _controller,
                      ),

And my CustomPainter looks like this:

class MyPainter extends CustomPainter {
  final double percentValue;
  final int moveDuration;
  final int holdDuration;

  MyPainter(
      {required this.percentValue,
      required this.moveDuration,
      required this.holdDuration});

  @override
  void paint(Canvas canvas, Size size) {
    // print("paint percent value: $percentValue");

    final holdingLinePaint = Paint()
      ..strokeWidth = 40
      ..color = Colors.amber
      ..strokeCap = StrokeCap.round;

    final linePaint = Paint()
      ..strokeWidth = 40
      ..color = Colors.red
      ..strokeCap = StrokeCap.round;

   
    const lineLength = 380;

    const leftPadding = 10.0;
    
// animation duration 
// moveDuration represents the two red ends and holdDuration represents the yellow part at the middle of the line
    final totalDuration = 2 * moveDuration + holdDuration;
    final dy = size.height / 2;

    final lineStart = Offset(leftPadding, dy);
    // lineEnd is animating according to the percentValue passed in
    final lineEnd = Offset(percentValue * 380 + leftPadding, dy);

    //  line one
    var firstEnd =
        Offset((lineLength / totalDuration) * moveDuration + leftPadding, dy);
    canvas.drawCircle(firstEnd, 10, Paint());
    // line two
    var secondStart = firstEnd;
    var secondEnd = Offset(
        (moveDuration + holdDuration) / totalDuration * lineLength +
            leftPadding,
        dy);
    canvas.drawCircle(secondEnd, 10, Paint());
    // line three
    var thirdStart = secondEnd;

    // divided into 3 phrases
    if (percentValue < (moveDuration / totalDuration)) {
      canvas.drawLine(lineStart, lineEnd, linePaint);
    } else if (percentValue >= (moveDuration / totalDuration) &&
        percentValue < (moveDuration + holdDuration) / totalDuration) {
      canvas.drawLine(secondStart, lineEnd, holdingLinePaint);
      canvas.drawLine(lineStart, firstEnd, linePaint);
    } else {
      canvas.drawLine(thirdStart, lineEnd, linePaint);
      canvas.drawLine(secondStart, secondEnd, holdingLinePaint);
      canvas.drawLine(lineStart, firstEnd, linePaint); 
    }


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

I'm animating an line like this

Basically, I am just animating a line but have to draw it with different colors according to different phrases.

Any advice?

Fever
  • 157
  • 2
  • 9
  • you can `await` the call of `forward` method and call it again in a loop or just in a row like : `await ctrl.forward(); await ctrl.forward(from: 0); await ctrl.forw...` – pskink Feb 07 '23 at 14:33
  • but actually I don't see any reasons why it has to be so complex - why don't you do that with one `forward` call and 3 [Interval](https://api.flutter.dev/flutter/animation/Interval-class.html)s for example? the docs say: "An Interval can be used to delay an animation. For example, a six second animation that uses an Interval with its begin set to 0.5 and its end set to 1.0 will essentially become a three-second animation that starts three seconds later." – pskink Feb 07 '23 at 15:15
  • Could you please elaborate a little bit on that Interval solution? – Fever Feb 08 '23 at 02:08
  • https://docs.flutter.dev/development/ui/animations/staggered-animations – pskink Feb 08 '23 at 07:33

0 Answers0