Flutter自定义Slider开发需求:实现如图所示的滑块样式
Flutter实现自定义样式Slider
要实现你需要的自定义Slider样式,核心是通过Flutter的SliderTheme配合自定义的滑块形状(SliderComponentShape)和轨道形状(SliderTrackShape)来实现,以下是完整的实现方案:
1. 自定义滑块样式
创建自定义的滑块形状类,实现实心圆+白色边框的滑块效果:
class CustomSliderThumbShape extends SliderComponentShape { final double thumbRadius; const CustomSliderThumbShape({this.thumbRadius = 10.0}); @override Size getPreferredSize(bool isEnabled, bool isDiscrete) { return Size.fromRadius(thumbRadius); } @override void paint( PaintingContext context, Offset center, { required Animation<double> activationAnimation, required Animation<double> enableAnimation, required bool isDiscrete, required TextPainter labelPainter, required RenderBox parentBox, required SliderThemeData sliderTheme, required TextDirection textDirection, required double value, required double textScaleFactor, required Size sizeWithOverflow, }) { final canvas = context.canvas; // 绘制实心滑块主体 final fillPaint = Paint() ..color = Colors.blue ..style = PaintingStyle.fill; canvas.drawCircle(center, thumbRadius, fillPaint); // 绘制滑块白色边框 final borderPaint = Paint() ..color = Colors.white ..style = PaintingStyle.stroke ..strokeWidth = 2.0; canvas.drawCircle(center, thumbRadius, borderPaint); } }
2. 自定义轨道样式
创建带渐变效果的轨道形状,区分激活和未激活区域:
class CustomSliderTrackShape extends RoundedRectSliderTrackShape { @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 || sliderTheme.trackHeight! <= 0) return; final canvas = context.canvas; final trackHeight = sliderTheme.trackHeight!; final trackRect = Rect.fromLTWH( offset.dx, offset.dy + (parentBox.size.height - trackHeight) / 2, parentBox.size.width, trackHeight, ); // 绘制未激活轨道(灰色背景) final inactivePaint = Paint() ..color = Colors.grey.shade300 ..style = PaintingStyle.fill; canvas.drawRRect( RRect.fromRectAndRadius(trackRect, Radius.circular(trackHeight / 2)), inactivePaint, ); // 绘制激活轨道(蓝色渐变) final activeTrackRect = Rect.fromLTWH( trackRect.left, trackRect.top, thumbCenter.dx - trackRect.left, trackRect.height, ); final activePaint = Paint() ..shader = LinearGradient( colors: [Colors.blue.shade400, Colors.blue.shade600], begin: Alignment.centerLeft, end: Alignment.centerRight, ).createShader(activeTrackRect); canvas.drawRRect( RRect.fromRectAndRadius(activeTrackRect, Radius.circular(trackHeight / 2)), activePaint, ); } }
3. 使用自定义Slider
通过SliderTheme包裹原生Slider,应用自定义样式:
double _currentValue = 0.5; @override Widget build(BuildContext context) { return Scaffold( body: Center( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 32.0), child: SliderTheme( data: SliderTheme.of(context).copyWith( trackHeight: 8.0, // 轨道高度 thumbShape: const CustomSliderThumbShape(thumbRadius: 12.0), // 滑块大小 trackShape: const CustomSliderTrackShape(), // 自定义轨道 overlayColor: Colors.blue.withOpacity(0.2), // 滑块点击反馈颜色 overlayShape: const RoundSliderOverlayShape(overlayRadius: 20.0), // 反馈区域大小 ), child: Slider( value: _currentValue, min: 0, max: 1, onChanged: (value) { setState(() => _currentValue = value); }, ), ), ), ), ); }
额外扩展
- 如果需要添加刻度标记,可以在Slider上下方添加
Row组件,根据min、max和divisions参数生成对应的刻度文本或线条。 - 可根据需求修改滑块颜色、轨道渐变色、尺寸等参数,适配不同设计风格。
- 若需离散型Slider,只需给
Slider添加divisions参数即可,自定义形状无需额外修改。
内容的提问来源于stack exchange,提问作者Shekhar J. Lobo
相关产品推荐
相关产品推荐

