skip to Main Content

How can I make a multicolor custom progress bar with animation? I have three values ​​that determine the length of each color. Animation trigger when app started. I’ve tried make it with SizeAnimation just to expand colored container but it was a bad way.

enter image description here

I try to make it with CustomPainter, but I do something wrong

 class MultiColorsLinePainter extends CustomPainter {
  const MultiColorsLinePainter({required this.point});
  final double point;
  @override
  void paint(Canvas canvas, Size size) {
    final activePaint = Paint()
      ..color = Colors.teal
      ..strokeWidth = 11
      ..strokeCap = StrokeCap.round;
    final frozenPaint = Paint()
      ..color = Colors.blue
      ..strokeWidth = 11
      ..strokeCap = StrokeCap.butt;
    final sellPaint = Paint()
      ..color = Colors.red
      ..strokeWidth = 11
      ..strokeCap = StrokeCap.round;

    final activeStartingPoint = Offset(0, size.height / 2);
    final activeEndingPoint = Offset(size.width * point, size.height / 2);

    final frozenStartingPoint = Offset(activeEndingPoint.dx, size.height / 2);
    final frozenEndingPoint = Offset(activeEndingPoint.dx * point, size.height / 2);

    final sellStartingPoint = Offset(frozenEndingPoint.dx, size.height / 2);
    final sellEndingPoint = Offset(frozenEndingPoint.dx * point, size.height / 2);

    canvas
      ..drawLine(activeStartingPoint, activeEndingPoint, activePaint)
      ..drawLine(frozenStartingPoint, frozenEndingPoint, frozenPaint)
      ..drawLine(sellStartingPoint, sellEndingPoint, sellPaint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) =>
      oldDelegate.paint != paint;
}

2

Answers


  1. Chosen as BEST ANSWER

    I made it myself with CustomPainter

      class MultiColorsLinePainter extends CustomPainter {
      const MultiColorsLinePainter({
        required this.point,
        required this.activeWidth,
        required this.frozenWidth,
        required this.sellWidth,
        required this.activeColor,
        required this.frozenColor,
        required this.sellColor,
      });
      final double point;
      final double activeWidth;
      final double frozenWidth;
      final double sellWidth;
      final Color activeColor;
      final Color frozenColor;
      final Color sellColor;
    
      @override
      void paint(Canvas canvas, Size size) {
        final activePaint = Paint()
          ..color = activeColor
          ..strokeWidth = 11;
    
        final frozenPaint = Paint()
          ..color = frozenColor
          ..strokeWidth = 11;
    
        final sellPaint = Paint()
          ..color = sellColor
          ..strokeWidth = 11;
    
        final activeStartingPoint = Offset(0, size.height / 2);
        final activeEndingPoint = Offset(
          point * activeWidth < activeWidth ? activeWidth * point : activeWidth,
          size.height / 2,
        );
    
        final frozenStartingPoint = Offset(activeEndingPoint.dx, size.height / 2);
        final frozenEndingPoint = Offset(
          point * (frozenWidth + activeWidth) < frozenWidth + activeWidth
              ? (frozenWidth + activeWidth) * point
              : frozenWidth + activeWidth,
          size.height / 2,
        );
    
        final sellStartingPoint = Offset(frozenEndingPoint.dx, size.height / 2);
        final sellEndingPoint = Offset(
          point * (frozenWidth + activeWidth + sellWidth) <
                  frozenWidth + activeWidth + sellWidth
              ? (frozenWidth + activeWidth + sellWidth) * point
              : (frozenWidth + activeWidth + sellWidth),
          size.height / 2,
        );
    
        canvas
          ..drawLine(activeStartingPoint, activeEndingPoint, activePaint)
          ..drawLine(frozenStartingPoint, frozenEndingPoint, frozenPaint)
          ..drawLine(sellStartingPoint, sellEndingPoint, sellPaint);
      }
    
      @override
      bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
    }
    

  2. There are two ways to create a nice ani animation here. One option is to have a Row with 3 sized boxes and 3 animation controllers firing in sequence.

    A better option may be to have a Row with 3 decorated containers each wrapped in Expanded widget. Each Expanded widget has its flex property set to relative width. Then you have another container in this row which has specific width. At first, you set its width to be as wide as the progress bar. Then you have an animation controller that changes its width down to zero. As this container gets smaller, the other 3 containers will expand to take all the space. It will look cool.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search