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

如何在Flutter中实现截图所示的CircularProgressIndicator()效果

你截图里的分段圆角圆形进度条,原生CircularProgressIndicator没有提供开箱即用的配置,以下是两种可直接运行的实现方案:

CircularProgressIndicator参考效果

方案1:自定义CustomPainter实现(无第三方依赖,灵活度最高)

直接复制下面的封装组件即可使用,核心参数都做了可配置:

import 'dart:math';
import 'package:flutter/material.dart';

class SegmentedCircularProgress extends StatelessWidget {
  /// 进度值,范围0.0~1.0
  final double progress;
  /// 进度条粗细
  final double strokeWidth;
  /// 分段数量,和截图匹配默认8段
  final int segmentCount;
  /// 分段之间的间隔角度
  final double gapAngle;
  /// 底部轨道颜色
  final Color trackColor;
  /// 进度条颜色
  final Color progressColor;
  /// 进度条起始角度,默认从正上方开始
  final double startAngle;

  const SegmentedCircularProgress({
    super.key,
    required this.progress,
    this.strokeWidth = 12,
    this.segmentCount = 8,
    this.gapAngle = 6 * pi / 180,
    this.trackColor = const Color(0xFFE5E7EB),
    this.progressColor = Colors.blue,
    this.startAngle = -pi / 2,
  });

  @override
  Widget build(BuildContext context) {
    return CustomPaint(
      painter: _SegmentedCircularProgressPainter(
        progress: progress,
        strokeWidth: strokeWidth,
        segmentCount: segmentCount,
        gapAngle: gapAngle,
        trackColor: trackColor,
        progressColor: progressColor,
        startAngle: startAngle,
      ),
    );
  }
}

class _SegmentedCircularProgressPainter extends CustomPainter {
  final double progress;
  final double strokeWidth;
  final int segmentCount;
  final double gapAngle;
  final Color trackColor;
  final Color progressColor;
  final double startAngle;

  _SegmentedCircularProgressPainter({
    required this.progress,
    required this.strokeWidth,
    required this.segmentCount,
    required this.gapAngle,
    required this.trackColor,
    required this.progressColor,
    required this.startAngle,
  });

  @override
  void paint(Canvas canvas, Size size) {
    final center = Offset(size.width / 2, size.height / 2);
    final radius = min(size.width, size.height) / 2 - strokeWidth / 2;

    final trackPaint = Paint()
      ..color = trackColor
      ..strokeWidth = strokeWidth
      ..strokeCap = StrokeCap.round
      ..style = PaintingStyle.stroke;

    final progressPaint = Paint()
      ..color = progressColor
      ..strokeWidth = strokeWidth
      ..strokeCap = StrokeCap.round
      ..style = PaintingStyle.stroke;

    final totalGapAngle = gapAngle * segmentCount;
    final singleSegmentSweep = (2 * pi - totalGapAngle) / segmentCount;
    final activeCount = (progress * segmentCount).ceil();

    for (int i = 0; i < segmentCount; i++) {
      final currentStart = startAngle + i * (singleSegmentSweep + gapAngle);
      canvas.drawArc(
        Rect.fromCircle(center: center, radius: radius),
        currentStart,
        singleSegmentSweep,
        false,
        i < activeCount ? progressPaint : trackPaint,
      );
    }
  }

  @override
  bool shouldRepaint(covariant _SegmentedCircularProgressPainter old) {
    return old.progress != progress;
  }
}

使用示例

外层包SizedBox控制尺寸即可:

SizedBox(
  width: 120,
  height: 120,
  child: SegmentedCircularProgress(
    progress: 0.6,
    progressColor: Colors.blueAccent,
  ),
)

参数调整说明:

  • 不需要分段效果的话,把segmentCount设为1、gapAngle设为0,就是普通的圆角圆形进度条
  • 修改gapAngle数值可以调整分段之间的空隙大小
  • 修改startAngle可以调整进度条的起始绘制位置

方案2:用第三方包快速实现

如果不想自己写绘制逻辑,可以用percent_indicator包快速搭建,缺点是分段效果的自定义灵活度不如自绘:

  1. 先在pubspec.yaml添加依赖:
dependencies:
  percent_indicator: ^4.2.3
  1. 基础使用代码:
import 'package:percent_indicator/circular_percent_indicator.dart';

CircularPercentIndicator(
  radius: 60,
  lineWidth: 10,
  percent: 0.6,
  progressColor: Colors.blue,
  backgroundColor: Colors.grey.shade200,
  circularStrokeCap: CircularStrokeCap.round,
)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 19:51:19