Flutter RangeSlider : How to display different value inside left and right thumbs?

135 Views Asked by At

I have a customized RangeSlider with 2 values: RangeValues.start / RangeValues.end.

How to put RangeValues.start in left thumb and RangeValues.end in right thumb?

As you can see value is the same on both thumbs

My CustomRangeSliderThumbShape :

class CustomRangeSliderThumbShape extends RangeSliderThumbShape {
  final RangeValues valueSlider;

  CustomRangeSliderThumbShape({required this.valueSlider});

  @override
  Size getPreferredSize(bool isEnabled, bool isDiscrete) {
    return const Size.fromRadius(20.0);
  }

  @override
  void paint(
    PaintingContext context,
    Offset center, {
    required Animation<double> activationAnimation,
    required Animation<double> enableAnimation,
    required SliderThemeData sliderTheme,
    bool? isDiscrete,
    bool? isEnabled,
    bool? isOnTop,
    TextDirection? textDirection,
    Thumb? thumb,
    bool? isPressed,
  }) {
    final Canvas canvas = context.canvas;

    // Draw the outer circle
    final outerRadius = 30.0;
    final outerPaint = Paint()..color = primaryColor;
    canvas.drawCircle(center, outerRadius, outerPaint);

    // Draw the inner circle
    final innerRadius = 28.0;
    final innerPaint = Paint()..color = Colors.white;
    canvas.drawCircle(center, innerRadius, innerPaint);

    // Draw the text
    final textStyle = TextStyle(
        color: Colors.black, fontWeight: FontWeight.bold, fontSize: 20);
    final textSpan = TextSpan(
      text: valueSlider.start.toInt().toString(),
      style: textStyle,
    );

    final textPainter = TextPainter(
      text: textSpan,
      textDirection: TextDirection.ltr,
    );

    textPainter.layout();

    textPainter.paint(
      canvas,
      Offset(
        center.dx - textPainter.width / 2,
        center.dy - textPainter.height / 2,
      ),
    );
  }
}
3

There are 3 best solutions below

1
pixel On

See If you look this below line, it's responsible of getting the same value in you both the start and end thumbs. So you need to change this.

text: valueSlider.start.toInt().toString(),

To display different values on the left and right thumbs, you need to pass a condition as thumb is left or right and display start and end range value accordingly:

import 'package:flutter/material.dart';

class CustomRangeSliderThumbShape extends RangeSliderThumbShape {
  final RangeValues valueSlider;
  final bool isLeft;

  CustomRangeSliderThumbShape({required this.leftValue, required this.rightValue});

  @override
  Size getPreferredSize(bool isEnabled, bool isDiscrete) {
    return const Size.fromRadius(20.0);
  }

  @override
  void paint(
    PaintingContext context,
    Offset center, {
    required Animation<double> activationAnimation,
    required Animation<double> enableAnimation,
    required SliderThemeData sliderTheme,
    bool? isDiscrete,
    bool? isEnabled,
    bool? isOnTop,
    TextDirection? textDirection,
    Thumb? thumb,
    bool? isPressed,
  }) {
    final Canvas canvas = context.canvas;

    // Draw the outer circle
    final outerRadius = 30.0;
    final outerPaint = Paint()..color = Colors.blue; // Adjust color as needed
    canvas.drawCircle(center, outerRadius, outerPaint);

    // Draw the inner circle
    final innerRadius = 28.0;
    final innerPaint = Paint()..color = Colors.white;
    canvas.drawCircle(center, innerRadius, innerPaint);

    // Draw the text
    final textStyle = TextStyle(
      color: Colors.black,
      fontWeight: FontWeight.bold,
      fontSize: 20,
    );

    final textSpan = TextSpan(
      text: thumb == isLeft ? valueSlider.start.toInt().toString() : valueSlider.end.toInt().toString(),
      style: textStyle,
    );

    final textPainter = TextPainter(
      text: textSpan,
      textDirection: textDirection ?? TextDirection.ltr,
    );

    textPainter.layout();

    textPainter.paint(
      canvas,
      Offset(
        center.dx - textPainter.width / 2,
        center.dy - textPainter.height / 2,
      ),
    );
  }
}
1
Zeelkumar Sojitra On

-- try to this code to create left and right thums slider bar in flutter

RangeSlider(
          values: _values,
          onChanged: (RangeValues newValues) {
            setState(() {
              _values = newValues;
            });
          },
          labels: RangeLabels(
            '${_values.start.round()}%',
            '${_values.end.round()}%',
          ),
          min: 0,
          max: 100,
        ),
0
Caveira Rainbow On

After a lot of searching, I finally found a solution, which I can now share with you:

class CustomRangeSliderThumbShape extends RangeSliderThumbShape {
  final RangeValues valueSlider;

  CustomRangeSliderThumbShape({required this.valueSlider});

  @override
  Size getPreferredSize(bool isEnabled, bool isDiscrete) {
    return const Size.fromRadius(20.0);
  }

  @override
  void paint(
    PaintingContext context,
    Offset center, {
    required Animation<double> activationAnimation,
    required Animation<double> enableAnimation,
    required SliderThemeData sliderTheme,
    bool? isDiscrete,
    bool? isEnabled,
    bool? isOnTop,
    TextDirection? textDirection,
    Thumb? thumb,
    bool? isPressed,
  }) {
    final Canvas canvas = context.canvas;

    // Draw the outer circle
    final outerRadius = 30.0;
    final outerPaint = Paint()..color = primaryColor;
    canvas.drawCircle(center, outerRadius, outerPaint);

    // Draw the inner circle
    final innerRadius = 28.0;
    final innerPaint = Paint()..color = Colors.white;
    canvas.drawCircle(center, innerRadius, innerPaint);

    // Draw the text
    final textStyle = TextStyle(
        color: Colors.black, fontWeight: FontWeight.bold, fontSize: 20);

    TextPainter textPainter;
    switch (textDirection!) {
      case TextDirection.rtl:
        switch (thumb!) {
          case Thumb.start:
            textPainter = TextPainter(
              text: TextSpan(
                text: valueSlider.end.toInt().toString(),
                style: textStyle,
              ),
              textDirection: TextDirection.rtl,
            );
            break;
          case Thumb.end:
            textPainter = TextPainter(
              text: TextSpan(
                text: valueSlider.start.toInt().toString(),
                style: textStyle,
              ),
              textDirection: TextDirection.rtl,
            );
            break;
        }
        break;
      case TextDirection.ltr:
        switch (thumb!) {
          case Thumb.start:
            textPainter = TextPainter(
              text: TextSpan(
                text: valueSlider.start.toInt().toString(),
                style: textStyle,
              ),
              textDirection: TextDirection.ltr,
            );
            break;
          case Thumb.end:
            textPainter = TextPainter(
              text: TextSpan(
                text: valueSlider.end.toInt().toString(),
                style: textStyle,
              ),
              textDirection: TextDirection.ltr,
            );
            break;
        }
        break;
    }

    textPainter.layout();

    textPainter.paint(
      canvas,
      Offset(
        center.dx - textPainter.width / 2,
        center.dy - textPainter.height / 2,
      ),
    );
  }
}

Result:

image result