咨询:能否在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
相关产品推荐
相关产品推荐

