如何在Flutter中实现截图所示的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包快速搭建,缺点是分段效果的自定义灵活度不如自绘:
- 先在
pubspec.yaml添加依赖:
dependencies: percent_indicator: ^4.2.3
- 基础使用代码:
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
相关产品推荐
相关产品推荐

