如何为Flutter Range Slider的非激活Thumb添加模糊阴影?
为Flutter RangeSlider的非激活Thumb添加模糊阴影
要给非激活状态的Thumb添加模糊阴影,核心是利用activationAnimation判断当前绘制的Thumb是否处于激活状态,再通过MaskFilter实现高斯模糊效果。你之前的代码错误地在单个paint方法里手动绘制了第二个Thumb,实际上RangeSlider的两个Thumb会分别调用paint方法,每个方法的offset就是对应Thumb的位置,无需手动偏移。
以下是修正后的完整代码:
class PriceRangeSlider extends StatelessWidget { const PriceRangeSlider({ Key? key, required this.currentRangeValues, required this.onChanged, required this.minPrice, required this.maxPrice, }) : super(key: key); final RangeValues currentRangeValues; final ValueChanged<RangeValues> onChanged; final double minPrice; final double maxPrice; @override Widget build(BuildContext context) { final ThemeColors colors = context.colors; final SliderThemeData sliderData = SliderTheme.of(context).copyWith( activeTrackColor: colors.darkText, inactiveTrackColor: colors.lightGrey, trackHeight: Di.p4, thumbColor: colors.contrastWhite, thumbShape: CustomThumbShape(), overlayShape: RoundSliderOverlayShape(overlayRadius: 0), ); return Padding( padding: const Pad(top: Di.p20), child: SliderTheme( data: sliderData, child: RangeSlider( values: currentRangeValues, min: minPrice, max: maxPrice, onChanged: onChanged, ), ), ); } } class CustomThumbShape extends SliderComponentShape { @override Size getPreferredSize(bool isEnabled, bool isDiscrete) { return Size(24.0, 24.0); } @override void paint( PaintingContext context, Offset offset, {required Animation<double> activationAnimation, required Animation<double> enableAnimation, required bool isDiscrete, required TextPainter labelPainter, required RenderBox parentBox, required Size sizeWithOverflow, required SliderThemeData sliderTheme, required TextDirection textDirection, required double textScaleFactor, required double value}) { final Canvas canvas = context.canvas; final bool isActive = activationAnimation.value > 0.5; final double outerRadius = 16.0; final double innerRadius = 12.0; // 配置阴影画笔:根据激活状态设置不同的模糊和透明度 final Paint shadowPaint = Paint() ..color = Colors.black.withOpacity(isActive ? 0.4 : 0.2) ..maskFilter = MaskFilter.blur(BlurStyle.normal, isActive ? 6 : 3) ..style = PaintingStyle.fill; final Paint outerPaint = Paint() ..color = Colors.red ..style = PaintingStyle.stroke ..strokeWidth = 2.0; final Paint innerPaint = Paint() ..color = Colors.black ..style = PaintingStyle.fill; // 先画阴影(要在最底层) canvas.drawCircle(offset, outerRadius + (isActive ? 6 : 4), shadowPaint); // 再画外层圆环 canvas.drawCircle(offset, outerRadius, outerPaint); // 最后画内层实心圆 canvas.drawCircle(offset, innerRadius, innerPaint); } }
关键修改说明:
- 判断激活状态:通过
activationAnimation.value > 0.5判断当前绘制的Thumb是否处于激活状态(用户触碰的那个)。 - 模糊阴影实现:使用
MaskFilter.blur(BlurStyle.normal, radius)给阴影添加高斯模糊效果,激活状态用更大的模糊半径和更高的透明度,非激活状态效果更淡。 - 层级正确:先绘制阴影,再绘制Thumb的外层和内层,保证阴影在Thumb下方。
- 移除错误绘制:删除了手动绘制第二个Thumb的代码,RangeSlider会自动为两个Thumb分别调用paint方法,每个方法的
offset就是对应Thumb的正确位置。
内容的提问来源于stack exchange,提问作者inkwelll075
相关产品推荐
相关产品推荐

