flutterprogress-indicator

how to customize progress indicator in flutter


Please I need a package or code sample on how to achieve this progress indicator as shown in the last image. It's a figma design that I need to replicate in the flutter app. The packages that I got didn't really give me what I want. I just need a way to achieve the progress indicator as shown in the imageenter image description here


Solution

  • You can try something like this:

    import 'package:flutter/material.dart';
    
    class SliderScreen extends StatelessWidget {
      const SliderScreen({super.key});
    
      @override
      Widget build(BuildContext context) {
        return const Scaffold(
          body: SafeArea(
            child: Padding(
              padding: EdgeInsets.all(20.0),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text('Headache'),
                  GradientSlider(
                    currentValue: 2,
                  ),
                  Text('Fever'),
                  GradientSlider(
                    currentValue: 3.5,
                  ),
                  Text('Pains'),
                  GradientSlider(
                    currentValue: 5.5,
                  ),
                  Text('Energy Levels'),
                  GradientSlider(
                    currentValue: 9,
                  ),
                ],
              ),
            ),
          ),
        );
      }
    }
    
    class GradientSlider extends StatefulWidget {
      final double currentValue;
    
      const GradientSlider({super.key, required this.currentValue});
    
      @override
      State<GradientSlider> createState() => _GradientSliderState();
    }
    
    class _GradientSliderState extends State<GradientSlider> {
      @override
      void initState() {
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        return Column(
          children: [
            SliderTheme(
              data: SliderTheme.of(context).copyWith(
                trackHeight: 8.0,
                activeTrackColor: Colors.transparent,
                inactiveTrackColor: Colors.transparent,
                thumbShape: const RoundSliderThumbShape(enabledThumbRadius: 12.0),
                overlayShape: const RoundSliderOverlayShape(overlayRadius: 24.0),
                trackShape: GradientSliderTrackShape(
                  gradient: const LinearGradient(
                    colors: [Colors.red, Colors.yellow, Colors.green],
                    stops: [0.0, 0.5, 1.0],
                  ),
                ),
              ),
              child: Slider(
                value: widget.currentValue,
                min: 0.0,
                max: 10.0,
                onChanged: (double value) {},
              ),
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: List.generate(11, (index) {
                return Text(
                  '$index',
                  style: const TextStyle(
                    fontSize: 14.0,
                    color: Colors.black, // Customize color as needed
                  ),
                );
              }),
            ),
          ],
        );
      }
    }
    
    class GradientSliderTrackShape extends SliderTrackShape {
      final LinearGradient gradient;
    
      GradientSliderTrackShape({required this.gradient});
    
      @override
      Rect getPreferredRect({
        required RenderBox parentBox,
        Offset offset = Offset.zero,
        required SliderThemeData sliderTheme,
        bool? isEnabled,
        bool? isDiscrete,
      }) {
        final double trackHeight = sliderTheme.trackHeight ?? 2.0;
        final double trackLeft = offset.dx;
        final double trackTop = offset.dy + (parentBox.size.height - trackHeight) / 2;
        final double trackRight = trackLeft + parentBox.size.width;
        final double trackBottom = trackTop + trackHeight;
        return Rect.fromLTRB(trackLeft, trackTop, trackRight, trackBottom);
      }
    
      @override
      void paint(
        PaintingContext context,
        Offset offset, {
        required RenderBox parentBox,
        required SliderThemeData sliderTheme,
        required Animation<double> enableAnimation,
        required Offset thumbCenter,
        Offset? secondaryOffset,
        bool? isEnabled,
        bool? isDiscrete,
        required TextDirection textDirection,
      }) {
        final Rect trackRect = getPreferredRect(
          parentBox: parentBox,
          sliderTheme: sliderTheme,
        );
    
        final Paint paint = Paint()
          ..shader = gradient.createShader(trackRect)
          ..style = PaintingStyle.fill;
    
        context.canvas.drawRRect(
          RRect.fromRectAndRadius(trackRect, const Radius.circular(4.0)),
          paint,
        );
      }
    }
    

    The output is: