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

如何为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);
  }
}

关键修改说明:

  1. 判断激活状态:通过activationAnimation.value > 0.5判断当前绘制的Thumb是否处于激活状态(用户触碰的那个)。
  2. 模糊阴影实现:使用MaskFilter.blur(BlurStyle.normal, radius)给阴影添加高斯模糊效果,激活状态用更大的模糊半径和更高的透明度,非激活状态效果更淡。
  3. 层级正确:先绘制阴影,再绘制Thumb的外层和内层,保证阴影在Thumb下方。
  4. 移除错误绘制:删除了手动绘制第二个Thumb的代码,RangeSlider会自动为两个Thumb分别调用paint方法,每个方法的offset就是对应Thumb的正确位置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 13:10:14