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

Flutter中如何为Slider轨道的divisions分段区间分别设置独立颜色

Flutter 实现分段着色自定义Slider

核心实现思路

Flutter原生Slider组件的轨道默认是统一填充色,要实现每个division分段独立着色的效果,核心是自定义Slider轨道形状,重写分段绘制逻辑,不需要引入第三方插件即可完成。

实现步骤

  • 编写可复用的分段轨道绘制类
    继承Flutter内置的SliderTrackShape基类,重写两个核心方法:
    • getPreferredRect:复用系统默认的轨道尺寸计算规则,保证轨道的高度、上下边距和原生Slider完全对齐,不会出现布局错位
    • paint:核心绘制逻辑,先根据轨道的总宽度计算每一段的宽度,逐段使用预设的颜色列表绘制圆角轨道块,最后叠加未选中区域的半透明暗化遮罩,模拟原生Slider的交互反馈
  • 挂载自定义轨道到SliderTheme
    将自定义的轨道形状赋值给SliderThemeData的trackShape参数,同时把原生默认的激活/非激活轨道颜色设为透明,避免和自定义绘制的彩色轨道重叠
  • 配置Slider组件的基础参数
    将Slider的divisions数值设置为和颜色列表长度一致,绑定值更新回调即可完成效果

完整代码示例

自定义轨道类

import 'package:flutter/material.dart';

class SegmentedTrackShape extends SliderTrackShape {
  // 每个分段对应的颜色列表
  final List<Color> segmentColors;

  const SegmentedTrackShape({required this.segmentColors});

  @override
  Rect getPreferredRect({
    required RenderBox parentBox,
    Offset offset = Offset.zero,
    required SliderThemeData sliderTheme,
    bool isEnabled = false,
    bool isDiscrete = false,
  }) {
    // 复用默认逻辑计算轨道的边界尺寸
    final double trackHeight = sliderTheme.trackHeight!;
    final double trackLeft = offset.dx;
    final double trackTop = offset.dy + (parentBox.size.height - trackHeight) / 2;
    final double 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 Offset thumbCenter,
    Offset? secondaryOffset,
    bool isEnabled = false,
    bool isDiscrete = false,
    required TextDirection textDirection,
  }) {
    final Paint segmentPaint = Paint();
    final Rect trackRect = getPreferredRect(
      parentBox: parentBox,
      offset: offset,
      sliderTheme: sliderTheme,
      isEnabled: isEnabled,
      isDiscrete: isDiscrete,
    );

    // 计算单段轨道的宽度,保证分段数和颜色列表长度对齐
    final double segmentWidth = trackRect.width / segmentColors.length;
    final Radius trackRadius = Radius.circular(trackRect.height / 2);

    // 从左到右逐段绘制彩色轨道块
    for (int i = 0; i < segmentColors.length; i++) {
      segmentPaint.color = segmentColors[i];
      final Rect segmentRect = Rect.fromLTWH(
        trackRect.left + i * segmentWidth,
        trackRect.top,
        segmentWidth,
        trackRect.height,
      );
      context.canvas.drawRRect(
        RRect.fromRectAndRadius(segmentRect, trackRadius),
        segmentPaint,
      );
    }

    // 绘制滑块右侧未选中区域的暗化遮罩,模拟原生交互反馈
    final Paint inactiveMaskPaint = Paint()..color = Colors.black12;
    final Rect inactiveAreaRect = Rect.fromLTRB(
      thumbCenter.dx,
      trackRect.top,
      trackRect.right,
      trackRect.bottom,
    );
    context.canvas.drawRRect(
      RRect.fromRectAndRadius(inactiveAreaRect, trackRadius),
      inactiveMaskPaint,
    );
  }
}

组件调用示例

// 当前滑块值
double currentValue = 0.3;
// 预设的分段颜色列表
final List<Color> _divisionColors = [
  Color(0xff8DF5DE),
  Color(0xffA8F58C),
  Color(0xffFCEC74),
  Color(0xffFCD376),
  Color(0xffFDB272),
  Color(0xffE27E5A),
];

SliderTheme(
  data: SliderThemeData(
    trackHeight: 8, // 轨道高度
    trackShape: SegmentedTrackShape(segmentColors: _divisionColors),
    // 隐藏原生默认轨道,避免和自定义绘制的轨道重叠
    activeTrackColor: Colors.transparent,
    inactiveTrackColor: Colors.transparent,
    thumbColor: Colors.white,
    thumbShape: const RoundSliderThumbShape(enabledThumbRadius: 12),
  ),
  child: Slider(
    value: currentValue,
    min: 0,
    max: 1,
    divisions: _divisionColors.length, // 分段数和颜色列表长度匹配
    onChanged: (value) {
      // 绑定值更新逻辑
      currentValue = value;
    },
  ),
)

注意事项

  • 必须保证Slider的divisions值和传入自定义轨道的颜色列表长度完全匹配,否则会出现分段数和颜色块数量错位的问题
  • 可以根据设计需求调整trackHeight(轨道高度)、enabledThumbRadius(滑块大小)、未选中遮罩的透明度,适配不同的视觉风格
  • 如果应用需要支持从右到左的RTL语言显示,需要在绘制逻辑中根据textDirection参数调整分段的绘制顺序,避免颜色排列方向颠倒

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.26 02:36:10