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

咨询:能否在Flutter中实现指定进度指示器?寻求技术帮助

Flutter 自定义分段环形进度指示器实现方案

完全可以实现这类分段环形进度指示器,不用依赖第三方包,通过CustomPaint自定义绘制是最灵活的方案,以下是具体实现思路和代码:

核心实现思路

  • 利用CustomPainter绘制多个独立弧形,每个弧形对应一个颜色进度段
  • 根据传入的各段进度值,计算每个弧形的扫过角度
  • 封装成可复用组件,支持自定义半径、线条宽度、颜色列表、进度列表等参数

完整代码示例

import 'package:flutter/material.dart';

class MultiSegmentProgress extends StatelessWidget {
  // 各段进度值(范围0-1)
  final List<double> segmentProgress;
  // 对应各段的颜色
  final List<Color> segmentColors;
  // 指示器半径
  final double radius;
  // 线条宽度
  final double strokeWidth;

  const MultiSegmentProgress({
    super.key,
    required this.segmentProgress,
    required this.segmentColors,
    this.radius = 100,
    this.strokeWidth = 12,
  }) : assert(segmentProgress.length == segmentColors.length, '进度列表与颜色列表长度必须一致');

  @override
  Widget build(BuildContext context) {
    return CustomPaint(
      size: Size(radius * 2, radius * 2),
      painter: _MultiSegmentPainter(
        progressList: segmentProgress,
        colorList: segmentColors,
        radius: radius,
        strokeWidth: strokeWidth,
      ),
    );
  }
}

class _MultiSegmentPainter extends CustomPainter {
  final List<double> progressList;
  final List<Color> colorList;
  final double radius;
  final double strokeWidth;

  _MultiSegmentPainter({
    required this.progressList,
    required this.colorList,
    required this.radius,
    required this.strokeWidth,
  });

  @override
  void paint(Canvas canvas, Size size) {
    final center = Offset(size.width / 2, size.height / 2);
    // 起始角度设为顶部(-90度转弧度)
    double currentStartAngle = -90 * (pi / 180);

    for (int i = 0; i < progressList.length; i++) {
      // 计算当前段的扫过弧度
      final sweepAngle = progressList[i] * 2 * pi;
      final paint = Paint()
        ..color = colorList[i]
        ..style = PaintingStyle.stroke
        ..strokeWidth = strokeWidth
        ..strokeCap = StrokeCap.round; // 可选:设置端点圆角样式

      canvas.drawArc(
        Rect.fromCircle(center: center, radius: radius - strokeWidth / 2),
        currentStartAngle,
        sweepAngle,
        false,
        paint,
      );

      // 更新下一段的起始角度
      currentStartAngle += sweepAngle;
    }
  }

  @override
  bool shouldRepaint(covariant _MultiSegmentPainter oldDelegate) {
    return progressList != oldDelegate.progressList ||
        colorList != oldDelegate.colorList ||
        radius != oldDelegate.radius ||
        strokeWidth != oldDelegate.strokeWidth;
  }
}

// 使用示例
void main() {
  runApp(const MaterialApp(
    home: Scaffold(
      body: Center(
        child: MultiSegmentProgress(
          segmentProgress: [0.3, 0.25, 0.2],
          segmentColors: [Colors.orange, Colors.blue, Colors.green],
          radius: 120,
          strokeWidth: 15,
        ),
      ),
    ),
  ));
}

扩展说明

  • 若需要添加背景环,可在循环绘制进度弧之前,先绘制一个灰色的完整环形
  • 动态更新进度时,只需修改segmentProgress列表并触发组件重建即可
  • 可根据需求调整strokeCap参数,切换端点为直角或圆角样式

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 15:02:17