使用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
相关产品推荐
相关产品推荐

