paint method

  1. @override
void paint(
  1. PaintingContext context,
  2. Offset offset, {
  3. required RenderBox parentBox,
  4. required SliderThemeData sliderTheme,
  5. required Animation<double> enableAnimation,
  6. required TextDirection textDirection,
  7. required Offset thumbCenter,
  8. Offset? secondaryOffset,
  9. bool isDiscrete = false,
  10. bool isEnabled = false,
  11. double additionalActiveTrackHeight = 2,
})
override

Paints the track shape based on the state passed to it.

The context argument is the same as the one that includes the Slider's render box.

The offset argument the offset of the origin of the parentBox to the origin of its context canvas. This shape must be painted relative to this offset. See PaintingContextCallback.

The parentBox argument is the RenderBox of the Slider. Its attributes, such as size, can be used to assist in painting this shape.

the sliderTheme argument is the theme assigned to the Slider that this shape belongs to.

The enableAnimation argument is an animation triggered when the Slider is enabled, and it reverses when the slider is disabled. The Slider is enabled when Slider.onChanged is not null.Use this to paint intermediate frames for this shape when the slider changes enabled state.

The thumbCenter argument is the offset of the center of the thumb relative to the origin of the PaintingContext.canvas. It can be used as the point that divides the track into 2 segments.

The secondaryOffset argument is the offset of the secondary value relative to the origin of the PaintingContext.canvas.

If not null, the track is divided into 3 segments.

The isEnabled argument is false when Slider.onChanged is null and true otherwise. When true, the slider will respond to input.

The isDiscrete argument is true if Slider.divisions is non-null. When true, the slider will render tick marks on top of the track.

The textDirection argument can be used to determine how the track segments are painted depending on whether they are active or not.

The track segment between the start of the slider and the thumb is the active track segment. The track segment between the thumb and the end of the slider is the inactive track segment. In TextDirection.ltr, the start of the slider is on the left, and in TextDirection.rtl, the start of the slider is on the right.

Implementation

@override
void paint(
  PaintingContext context,
  Offset offset, {
  required RenderBox parentBox,
  required SliderThemeData sliderTheme,
  required Animation<double> enableAnimation,
  required TextDirection textDirection,
  required Offset thumbCenter,
  Offset? secondaryOffset,
  bool isDiscrete = false,
  bool isEnabled = false,
  double additionalActiveTrackHeight = 2,
}) {
  assert(sliderTheme.disabledActiveTrackColor != null);
  assert(sliderTheme.disabledInactiveTrackColor != null);
  assert(sliderTheme.activeTrackColor != null);
  assert(sliderTheme.inactiveTrackColor != null);
  assert(sliderTheme.thumbShape != null);
  // If the slider [SliderThemeData.trackHeight] is less than or equal to 0,
  // then it makes no difference whether the track is painted or not,
  // therefore the painting can be a no-op.
  if (sliderTheme.trackHeight == null || sliderTheme.trackHeight! <= 0) {
    return;
  }

  // Assign the track segment paints, which are leading: active and
  // trailing: inactive.
  final ColorTween activeTrackColorTween = ColorTween(begin: sliderTheme.disabledActiveTrackColor, end: sliderTheme.activeTrackColor);
  final ColorTween inactiveTrackColorTween = ColorTween(begin: sliderTheme.disabledInactiveTrackColor, end: sliderTheme.inactiveTrackColor);
  final Paint activePaint = Paint()..color = activeTrackColorTween.evaluate(enableAnimation)!;
  final Paint inactivePaint = Paint()..color = inactiveTrackColorTween.evaluate(enableAnimation)!;
  final (Paint leftTrackPaint, Paint rightTrackPaint) = switch (textDirection) {
    TextDirection.ltr => (activePaint, inactivePaint),
    TextDirection.rtl => (inactivePaint, activePaint),
  };

  final Rect trackRect = getPreferredRect(
    parentBox: parentBox,
    offset: offset,
    sliderTheme: sliderTheme,
    isEnabled: isEnabled,
    isDiscrete: isDiscrete,
  );
  final Radius trackRadius = Radius.circular(trackRect.height / 2);
  final Radius activeTrackRadius = Radius.circular((trackRect.height + additionalActiveTrackHeight) / 2);
  final bool isLTR = textDirection == TextDirection.ltr;
  final bool isRTL = textDirection == TextDirection.rtl;

  final bool drawInactiveTrack = thumbCenter.dx < (trackRect.right - (sliderTheme.trackHeight! / 2));
  if (drawInactiveTrack) {
    // Draw the inactive track segment.
    context.canvas.drawRRect(
      RRect.fromLTRBR(
        thumbCenter.dx - (sliderTheme.trackHeight! / 2),
        isRTL ? trackRect.top - (additionalActiveTrackHeight / 2) : trackRect.top,
        trackRect.right,
        isRTL ? trackRect.bottom + (additionalActiveTrackHeight / 2) : trackRect.bottom,
        isLTR ? trackRadius : activeTrackRadius,
      ),
      rightTrackPaint,
    );
  }
  final bool drawActiveTrack = thumbCenter.dx > (trackRect.left + (sliderTheme.trackHeight! / 2));
  if (drawActiveTrack) {
    // Draw the active track segment.
    context.canvas.drawRRect(
      RRect.fromLTRBR(
        trackRect.left,
        isLTR ? trackRect.top - (additionalActiveTrackHeight / 2): trackRect.top,
        thumbCenter.dx + (sliderTheme.trackHeight! / 2),
        isLTR ? trackRect.bottom + (additionalActiveTrackHeight / 2) : trackRect.bottom,
        isLTR ? activeTrackRadius : trackRadius,
      ),
      leftTrackPaint,
    );
  }

  final bool showSecondaryTrack = (secondaryOffset != null) &&
      (isLTR ? (secondaryOffset.dx > thumbCenter.dx) : (secondaryOffset.dx < thumbCenter.dx));

  if (showSecondaryTrack) {
    final ColorTween secondaryTrackColorTween = ColorTween(begin: sliderTheme.disabledSecondaryActiveTrackColor, end: sliderTheme.secondaryActiveTrackColor);
    final Paint secondaryTrackPaint = Paint()..color = secondaryTrackColorTween.evaluate(enableAnimation)!;
    if (isLTR) {
      context.canvas.drawRRect(
        RRect.fromLTRBAndCorners(
          thumbCenter.dx,
          trackRect.top,
          secondaryOffset.dx,
          trackRect.bottom,
          topRight: trackRadius,
          bottomRight: trackRadius,
        ),
        secondaryTrackPaint,
      );
    } else {
      context.canvas.drawRRect(
        RRect.fromLTRBAndCorners(
          secondaryOffset.dx,
          trackRect.top,
          thumbCenter.dx,
          trackRect.bottom,
          topLeft: trackRadius,
          bottomLeft: trackRadius,
        ),
        secondaryTrackPaint,
      );
    }
  }
}