如何编辑Custom TrackShape?

发布于 2025-01-24 10:03:24 字数 521 浏览 0 评论 0 原文

我正在为一个看起来像这样的项目设计一个自定义轨道形状:

我已经完成了大部分代码,最终得到了此结果:

“在此处输入图像说明”

除了圆形的侧面(我要修复的那些),我需要实现:

  1. 下移动标签,
  2. 如果可能的话,将标签在更改标签尺寸
  3. 以自定义TrackHeight,以使其在一端较小,而另一端则较小。

I am designing a custom track shape for a project that looks like this:
enter image description here

and I already finished most of the code, I ended up with this result:

enter image description here

aside from the rounded sides (those I'll fix), I need to achieve:

  1. Move the label under
  2. Change the label dimensions if possible
  3. Customize the trackheight to make it smaller on one end and larger on the other.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

蝶…霜飞 2025-01-31 10:03:24

简而言之:
将您的 slider ()包裹在a slidertheme ()中,并为其提供包含A 自定义轨道形状的适当 sliderThemedata () >和自定义的拇指形状

customTrackShape()

class CustomTrackShape extends SliderTrackShape {

  const CustomTrackShape({
  });

  @override
  Rect getPreferredRect({
    required final RenderBox parentBox,
    required final SliderThemeData sliderTheme,
    final bool isDiscrete = true,
    final bool isEnabled = true,
    final Offset offset = Offset.zero,
  }) {
    final double overlayWidth =
        sliderTheme.overlayShape!.getPreferredSize(isEnabled, isDiscrete).width;
    final double trackHeight = sliderTheme.trackHeight ?? 20;
    final double trackLeft = offset.dx + overlayWidth / 2;
    final double trackTop =
        offset.dy + (parentBox.size.height - trackHeight) / 2;
    // Although this works for a material, perhaps the default
    // rectangular track should be padded not just by the overlay, but by the
    // max of the thumb and the overlay, in case there is no overlay.
    final double trackWidth = parentBox.size.width - overlayWidth;
    return Rect.fromLTWH(trackLeft, trackTop, trackWidth, trackHeight);
  }

  @override
  void paint(
    final PaintingContext context,
    final Offset offset, {
    required final RenderBox parentBox,
    required final SliderThemeData sliderTheme,
    required final Animation<double> enableAnimation,
    required final Offset thumbCenter,
    required final TextDirection textDirection,
    final Offset? secondaryOffset,
    final bool isEnabled = true,
    final bool isDiscrete = true,
  }) {
    final Rect trackRectangle = getPreferredRect(
      parentBox: parentBox,
      offset: offset,
      sliderTheme: sliderTheme,
      isEnabled: isEnabled,
      isDiscrete: isDiscrete,
    
    const verticalOffset = const Offset(0, 20);

    context.canvas.drawPath(
        Path()
          ..addPolygon(
            [
              trackRectangle.bottomLeft - verticalOffset,
              trackRectangle.bottomRight,
              trackRectangle.topRight,
              trackRectangle.topLeft + verticalOffset,
              trackRectangle.bottomLeft - verticalOffset,
            ],
            true,
          ),
        Paint()..color = sliderTheme.activeTrackColor);
  }
}

customThumbShape()

class CustomThumbShape extends SliderComponentShape {
  CustomThumbShape({
    this.thumbRadius = 15,
  });
  final double thumbRadius;
  @override
  Size getPreferredSize(final bool isEnabled, final bool isDiscrete) =>
      Size.fromRadius(thumbWidth);

  @override
  void paint(
    final PaintingContext context,
    final Offset center, {
    required final Animation<double> activationAnimation,
    required final Animation<double> enableAnimation,
    required final RenderBox parentBox,
    required final Size sizeWithOverflow,
    required final SliderThemeData sliderTheme,
    required final TextDirection textDirection,
    required final TextPainter labelPainter,
    required final bool isDiscrete,
    required final double textScaleFactor,
    required final double value,
  }) {
    final Canvas canvas = context.canvas;
    final paint = Paint()
      ..color = sliderTheme.thumbColor;

    final TextSpan textSpan = TextSpan(
      text: value,
    );

    labelPainter
      ..text = textSpan
      ..textAlign = TextAlign.center
      ..textDirection = textDirection
      ..layout();

    final Offset textOffset = Offset(
      center.dx - (labelPainter.width / 2),
      center.dy + (sliderTheme.trackHeight! * 0.8),
    );

    final Offset p1 = Offset(
      center.dx,
      center.dy + sliderTheme.trackHeight! / 2,
    );
    final Offset p2 = Offset(
      center.dx,
      center.dy - sliderTheme.trackHeight! / 2,
    );

    canvas.drawCircle(center, thumbWidth, paint);
    if (isTouched) {
      labelPainter.paint(
        canvas,
        textOffset,
      );
    }
  }
}

您还应考虑在 slideThemedata ()中设置滑块颜色和其他主题属性。

In short:
Wrap your Slider() inside a SliderTheme() and provide it with proper SliderThemeData() containing a custom track shape and a custom thumb shape.

CustomTrackShape()

class CustomTrackShape extends SliderTrackShape {

  const CustomTrackShape({
  });

  @override
  Rect getPreferredRect({
    required final RenderBox parentBox,
    required final SliderThemeData sliderTheme,
    final bool isDiscrete = true,
    final bool isEnabled = true,
    final Offset offset = Offset.zero,
  }) {
    final double overlayWidth =
        sliderTheme.overlayShape!.getPreferredSize(isEnabled, isDiscrete).width;
    final double trackHeight = sliderTheme.trackHeight ?? 20;
    final double trackLeft = offset.dx + overlayWidth / 2;
    final double trackTop =
        offset.dy + (parentBox.size.height - trackHeight) / 2;
    // Although this works for a material, perhaps the default
    // rectangular track should be padded not just by the overlay, but by the
    // max of the thumb and the overlay, in case there is no overlay.
    final double trackWidth = parentBox.size.width - overlayWidth;
    return Rect.fromLTWH(trackLeft, trackTop, trackWidth, trackHeight);
  }

  @override
  void paint(
    final PaintingContext context,
    final Offset offset, {
    required final RenderBox parentBox,
    required final SliderThemeData sliderTheme,
    required final Animation<double> enableAnimation,
    required final Offset thumbCenter,
    required final TextDirection textDirection,
    final Offset? secondaryOffset,
    final bool isEnabled = true,
    final bool isDiscrete = true,
  }) {
    final Rect trackRectangle = getPreferredRect(
      parentBox: parentBox,
      offset: offset,
      sliderTheme: sliderTheme,
      isEnabled: isEnabled,
      isDiscrete: isDiscrete,
    
    const verticalOffset = const Offset(0, 20);

    context.canvas.drawPath(
        Path()
          ..addPolygon(
            [
              trackRectangle.bottomLeft - verticalOffset,
              trackRectangle.bottomRight,
              trackRectangle.topRight,
              trackRectangle.topLeft + verticalOffset,
              trackRectangle.bottomLeft - verticalOffset,
            ],
            true,
          ),
        Paint()..color = sliderTheme.activeTrackColor);
  }
}

CustomThumbShape()

class CustomThumbShape extends SliderComponentShape {
  CustomThumbShape({
    this.thumbRadius = 15,
  });
  final double thumbRadius;
  @override
  Size getPreferredSize(final bool isEnabled, final bool isDiscrete) =>
      Size.fromRadius(thumbWidth);

  @override
  void paint(
    final PaintingContext context,
    final Offset center, {
    required final Animation<double> activationAnimation,
    required final Animation<double> enableAnimation,
    required final RenderBox parentBox,
    required final Size sizeWithOverflow,
    required final SliderThemeData sliderTheme,
    required final TextDirection textDirection,
    required final TextPainter labelPainter,
    required final bool isDiscrete,
    required final double textScaleFactor,
    required final double value,
  }) {
    final Canvas canvas = context.canvas;
    final paint = Paint()
      ..color = sliderTheme.thumbColor;

    final TextSpan textSpan = TextSpan(
      text: value,
    );

    labelPainter
      ..text = textSpan
      ..textAlign = TextAlign.center
      ..textDirection = textDirection
      ..layout();

    final Offset textOffset = Offset(
      center.dx - (labelPainter.width / 2),
      center.dy + (sliderTheme.trackHeight! * 0.8),
    );

    final Offset p1 = Offset(
      center.dx,
      center.dy + sliderTheme.trackHeight! / 2,
    );
    final Offset p2 = Offset(
      center.dx,
      center.dy - sliderTheme.trackHeight! / 2,
    );

    canvas.drawCircle(center, thumbWidth, paint);
    if (isTouched) {
      labelPainter.paint(
        canvas,
        textOffset,
      );
    }
  }
}

you should also consider setting your slider colors and other theme properties in the SliderThemeData().

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文