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

Flutter如何通过Triangle Slider Track Shape实现Windows音量滑块

Flutter实现Windows控制面板风格音量滑块

Windows原生音量滑块参考效果

基于自定义Slider轨道形状实现,无需引入第三方依赖,直接编写代码即可完成效果。

核心实现逻辑

Windows音量滑块的视觉特征非常明确:

  • 轨道高度4px,滑块左侧为系统蓝色激活态,右侧为浅灰色未激活态
  • 滑块手柄为竖置白色圆角矩形,带1px浅灰色描边
  • 拖拽时无多余水波纹效果,交互反馈干净

如果要基于TriangleSliderTrackShape改造,只需要替换原类中三角路径的绘制逻辑,改为绘制平直的圆角矩形轨道即可,完整可运行代码如下:

1. 自定义轨道形状

import 'package:flutter/material.dart';

class WindowsVolumeTrackShape extends SliderTrackShape {
  const WindowsVolumeTrackShape();

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

  @override
  void paint(
    PaintingContext context,
    Offset offset, {
    required RenderBox parentBox,
    required SliderThemeData sliderTheme,
    required Animation<double> enableAnimation,
    required TextDirection textDirection,
    required Offset thumbCenter,
    Offset? secondaryOffset,
    bool isDiscrete = false,
    bool isEnabled = false,
  }) {
    final canvas = context.canvas;
    final trackRect = getPreferredRect(
      parentBox: parentBox,
      offset: offset,
      sliderTheme: sliderTheme,
      isEnabled: isEnabled,
      isDiscrete: isDiscrete,
    );

    // 绘制未激活灰色轨道
    canvas.drawRRect(
      RRect.fromRectAndRadius(trackRect, const Radius.circular(0.5)),
      Paint()..color = const Color(0xFFE6E6E6),
    );

    // 绘制激活蓝色轨道
    final activeRect = Rect.fromLTRB(
      trackRect.left,
      trackRect.top,
      thumbCenter.dx,
      trackRect.bottom,
    );
    canvas.drawRRect(
      RRect.fromRectAndRadius(activeRect, const Radius.circular(0.5)),
      Paint()..color = const Color(0xFF0078D7),
    );
  }
}

2. 自定义滑块手柄形状

class WindowsVolumeThumbShape extends SliderComponentShape {
  const WindowsVolumeThumbShape({
    this.width = 8,
    this.height = 20,
    this.radius = 2,
  });

  final double width;
  final double height;
  final double radius;

  @override
  Size getPreferredSize(bool isEnabled, bool isDiscrete) => Size(width, height);

  @override
  void paint(
    PaintingContext context,
    Offset center, {
    required Animation<double> enableAnimation,
    required TextDirection textDirection,
    required SliderThemeData sliderTheme,
    bool isDiscrete = false,
    bool isEnabled = false,
  }) {
    final canvas = context.canvas;
    final thumbRect = Rect.fromCenter(center: center, width: width, height: height);
    final rRect = RRect.fromRectAndRadius(thumbRect, Radius.circular(radius));
    // 白色填充
    canvas.drawRRect(rRect, Paint()..color = Colors.white);
    // 灰色描边
    canvas.drawRRect(
      rRect,
      Paint()
        ..color = const Color(0xFFCCCCCC)
        ..style = PaintingStyle.stroke
        ..strokeWidth = 1,
    );
  }
}

3. 组件集成使用

class VolumeSlider extends StatefulWidget {
  const VolumeSlider({super.key, required this.onVolumeChange});
  final ValueChanged<double> onVolumeChange;

  @override
  State<VolumeSlider> createState() => _VolumeSliderState();
}

class _VolumeSliderState extends State<VolumeSlider> {
  double _currentVolume = 0.65;

  @override
  Widget build(BuildContext context) {
    return SliderTheme(
      data: SliderThemeData(
        trackHeight: 4,
        trackShape: const WindowsVolumeTrackShape(),
        thumbShape: const WindowsVolumeThumbShape(),
        overlayShape: SliderComponentShape.noOverlay,
      ),
      child: Slider(
        value: _currentVolume,
        onChanged: (val) {
          setState(() => _currentVolume = val);
          widget.onVolumeChange(val);
        },
      ),
    );
  }
}

参数调整说明

  • 如果需要基于现有TriangleSliderTrackShape修改,直接把原类paint方法中绘制三角形路径的代码删除,替换为上面的圆角矩形轨道绘制逻辑即可
  • 色值、尺寸参数完全对齐Windows10/11原生音量控件,可根据实际显示需求微调
  • 不需要的水波纹、刻度高亮效果可以通过SliderThemeData的overlay、tick等属性关闭

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.31 12:51:21