Caveira Rainbow
Caveira Rainbow

Reputation: 11

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

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,
      ),
    );
  }
}

Upvotes: 0

Views: 385

Answers (3)

Caveira Rainbow
Caveira Rainbow

Reputation: 11

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

Upvotes: 1

Zeelkumar Sojitra
Zeelkumar Sojitra

Reputation: 279

-- 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,
        ),

Upvotes: 0

pixel
pixel

Reputation: 1059

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,
      ),
    );
  }
}

Upvotes: 0

Related Questions