1

I created a custom widget in flutter using custom painter. Its a status bar. I wanted to animate it, but now a problem is occurring that I don't know how to fix.

The bar consists of a line and several dots, depending on the status. When animating this bar, the line is correctly animated, but the dot is appearing to early, it just pops in.

example of how my widget is currently animating (can't post inline yet)

How can I choose when the dot animates?

This is the code I use for animating my widget:

class _StatusBarState extends State<StatusBar> with TickerProviderStateMixin {
  late AnimationController _animationController;

  @override
  void initState() {
    super.initState();
    _animationController = AnimationController(
        vsync: this,
        duration: Duration(seconds: 1),
        lowerBound: 1,
        upperBound: widget.states.length.toDouble());
  }

  @override
  void didUpdateWidget(covariant StatusBar oldWidget) {
    super.didUpdateWidget(oldWidget);
    _animationController.animateTo(widget.currentState.toDouble());
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        AnimatedBuilder(
          animation: _animationController,
          builder: (BuildContext buildContext, Widget? child) => Container(
            height: 50,
            width: MediaQuery.of(context).size.width * 0.75,
            child: CustomPaint(
              painter: _RentalStatusBarPainter(
                  context: context,
                  currentState: _animationController.value,
                  states: widget.states,
                  failed: widget.error),
            ),
          ),
        ),
        Container(
          width: MediaQuery.of(context).size.width * 0.85,
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: widget.states
                .map((e) => widget.states.indexOf(e) == widget.currentState - 1
                    ? Text(
                        e,
                        style: Theme.of(context).textTheme.subtitle1,
                      )
                    : Text(
                        e,
                        style: Theme.of(context).textTheme.caption,
                      ))
                .toList(),
          ),
        ),
        SizedBox(height: 10),
      ],
    );
  }
}

And this is the custom widget that is being painted:

@override
  void paint(Canvas canvas, Size size) {
    int currentStateInt = currentState.toInt();
    final paint = Paint()
      ..color = Theme.of(context).cardColor
      ..style = PaintingStyle.stroke
      ..strokeWidth = 5
      ..strokeCap = StrokeCap.round;

    final dotspaint = Paint()
      ..color = Theme.of(context).cardColor
      ..style = PaintingStyle.fill;

    final filledpaint = Paint()
      ..color = failed
          ? Theme.of(context).colorScheme.error
          : Theme.of(context).colorScheme.secondary
      ..style = PaintingStyle.stroke
      ..strokeWidth = 5
      ..strokeCap = StrokeCap.round;

    final filleddotspaint = Paint()
      ..color = failed
          ? Theme.of(context).colorScheme.error
          : Theme.of(context).colorScheme.secondary
      ..style = PaintingStyle.fill
      ..strokeCap = StrokeCap.round;

    //draw the background
    canvas.drawLine(
      Offset(0, size.height / 2),
      Offset(size.width, size.height / 2),
      paint,
    );

    for (int i = 0; i < numberOfStates; i++) {
      final double x = size.width * i / (numberOfStates - 1);

      canvas.drawCircle(Offset(x, size.height / 2), 10, dotspaint);
    }

    //draw the filled out stuff
    canvas.drawLine(
      Offset(0, size.height / 2),
      Offset(size.width * (currentState - 1) / (numberOfStates - 1),
          size.height / 2),
      filledpaint,
    );

    for (int i = 0; i < currentState; i++) {
      final double x = size.width * i / (numberOfStates - 1);

      canvas.drawCircle(Offset(x, size.height / 2), 10, filleddotspaint);
    }
  }

Any ideas or insights into how this "automatic" animation actually works is deeply appreciated!

Anton

Tony1704
  • 11
  • 1

1 Answers1

0

I actually found a workaround for this, and have an assumption of why my circles were not animated:

for (int i = 0; i < currentState - 1; i++) {
    final double x = size.width * i / (numberOfStates - 1);

    canvas.drawCircle(Offset(x, size.height / 2), 10, filleddotspaint);
}

final double x = size.width * (currentState - 1) / (numberOfStates - 1);

canvas.drawCircle(Offset(x, size.height / 2), 10, filleddotspaint);

I changed the last circle to be drawn outside of the for loop. This seems to be enough for the framework to detect that this is something that it should animate. Maybe the for loop confused it in some way?

Tony1704
  • 11
  • 1