You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用syncfusion_flutter_sliders实现正负值滑块及单侧轨道高亮

问题

使用syncfusion_flutter_sliders包时,能否实现支持正负值选择的滑块?具体需求如下:

  • 默认值为0
  • 向左滑动可选择0到-1之间的数值,向右滑动可选择0到1之间的数值
  • 仅高亮滑块拇指的左侧或右侧轨道

示例效果如下:
示例截图

解决方案

完全可以实现,核心思路是设置滑块的取值范围为-1到1,并通过自定义轨道样式控制高亮区域,具体实现步骤如下:

1. 自定义轨道形状类

创建继承自RoundedRectSliderTrackShape的自定义类,重写paint方法,根据滑块拇指位置决定高亮轨道范围:

class CustomTrackShape extends RoundedRectSliderTrackShape {
  @override
  Rect getPreferredRect({
    required RenderBox parentBox,
    Offset offset = Offset.zero,
    required SliderThemeData sliderTheme,
    bool isEnabled = false,
    bool isDiscrete = false,
  }) {
    final trackHeight = sliderTheme.trackHeight;
    final trackLeft = offset.dx;
    final trackTop = offset.dy + (parentBox.size.height - trackHeight!) / 2;
    final trackWidth = parentBox.size.width;
    return Rect.fromLTWH(trackLeft, trackTop, trackWidth, trackHeight);
  }

  @override
  void paint(PaintingContext context, Offset offset,
      {required RenderBox parentBox,
      required SliderThemeData sliderTheme,
      required Animation<double> enableAnimation,
      required TextDirection textDirection,
      required Offset thumbCenter,
      bool isDiscrete = false,
      bool isEnabled = false,
      double additionalActiveTrackHeight = 2}) {
    if (sliderTheme.trackHeight == null) return;

    final trackRect = getPreferredRect(
      parentBox: parentBox,
      offset: offset,
      sliderTheme: sliderTheme,
      isEnabled: isEnabled,
      isDiscrete: isDiscrete,
    );

    final activePaint = Paint()..color = sliderTheme.activeTrackColor!;
    final inactivePaint = Paint()..color = sliderTheme.inactiveTrackColor!;

    double left, right;
    // 根据拇指位置判断高亮区域
    if (thumbCenter.dx < trackRect.center.dx) {
      // 左滑时,高亮轨道左端到拇指的区域
      left = trackRect.left;
      right = thumbCenter.dx;
    } else {
      // 右滑时,高亮拇指到轨道右端的区域
      left = thumbCenter.dx;
      right = trackRect.right;
    }

    // 绘制高亮轨道
    context.canvas.drawRRect(
      RRect.fromLTRBAndCorners(
        left,
        trackRect.top,
        right,
        trackRect.bottom,
        topLeft: const Radius.circular(4),
        topRight: const Radius.circular(4),
        bottomLeft: const Radius.circular(4),
        bottomRight: const Radius.circular(4),
      ),
      activePaint,
    );

    // 绘制未高亮轨道
    final inactiveLeft = thumbCenter.dx < trackRect.center.dx ? thumbCenter.dx : trackRect.left;
    final inactiveRight = thumbCenter.dx < trackRect.center.dx ? trackRect.right : thumbCenter.dx;

    context.canvas.drawRRect(
      RRect.fromLTRBAndCorners(
        inactiveLeft,
        trackRect.top,
        inactiveRight,
        trackRect.bottom,
        topLeft: const Radius.circular(4),
        topRight: const Radius.circular(4),
        bottomLeft: const Radius.circular(4),
        bottomRight: const Radius.circular(4),
      ),
      inactivePaint,
    );
  }
}

2. 使用自定义轨道的SfSlider

在布局中配置SfSlider,设置取值范围、初始值并指定自定义轨道形状:

double _value = 0.0;

@override
Widget build(BuildContext context) {
  return Scaffold(
    body: Center(
      child: SfSlider(
        min: -1.0,
        max: 1.0,
        value: _value,
        onChanged: (newValue) {
          setState(() {
            _value = newValue;
          });
        },
        trackShape: CustomTrackShape(),
        activeColor: Colors.blue, // 高亮轨道颜色
        inactiveColor: Colors.grey.shade300, // 未高亮轨道颜色
      ),
    ),
  );
}

实现说明

  • 通过min: -1.0和max: 1.0设置滑块取值范围,初始值_value = 0.0满足默认值要求。
  • 自定义的CustomTrackShape会根据拇指位置动态调整高亮范围:左滑时高亮左侧轨道,右滑时高亮右侧轨道,完全匹配需求中的轨道高亮效果。

内容的提问来源于stack exchange,提问作者Captivity

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 23:05:23