如何在Flutter中实现弧形进度条(ArcProgress Bar)?求解决方案
我懂你想要的那种弧形进度条——不是整圆,而是一段带进度的圆弧对吧?系统自带的CircularProgressIndicator和percent_indicator包确实没法灵活控制弧形的起止角度和样式,那咱们直接用CustomPaint自己画一个,完全能实现你要的效果!
实现思路
通过自定义CustomPainter来绘制两段圆弧:一段是背景灰色弧,另一段是根据进度变化的前景彩色弧。你可以自由调整弧形的起止角度、线宽、颜色等参数,完全匹配你的设计需求。
完整代码示例
1. 自定义绘制器(ArcProgressPainter)
这个类负责实际绘制弧形进度条的逻辑:
import 'dart:math'; import 'package:flutter/material.dart'; class ArcProgressPainter extends CustomPainter { final double progress; final Color progressColor; final Color backgroundColor; final double strokeWidth; final double startAngle; final double sweepAngle; ArcProgressPainter({ required this.progress, required this.progressColor, required this.backgroundColor, required this.strokeWidth, // 默认从左上方135度开始,扫过270度形成一个大弧形 this.startAngle = 135 * pi / 180, this.sweepAngle = 270 * pi / 180, }); @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 backgroundPaint = Paint() ..color = backgroundColor ..style = PaintingStyle.stroke ..strokeWidth = strokeWidth ..strokeCap = StrokeCap.round; // 可选:让弧形两端变成圆角 canvas.drawArc( Rect.fromCircle(center: center, radius: radius), startAngle, sweepAngle, false, backgroundPaint, ); // 绘制进度弧形 final progressPaint = Paint() ..color = progressColor ..style = PaintingStyle.stroke ..strokeWidth = strokeWidth ..strokeCap = StrokeCap.round; final progressSweepAngle = sweepAngle * progress; canvas.drawArc( Rect.fromCircle(center: center, radius: radius), startAngle, progressSweepAngle, false, progressPaint, ); } @override bool shouldRepaint(covariant ArcProgressPainter oldDelegate) { // 只有当关键参数变化时才重绘,提升性能 return oldDelegate.progress != progress || oldDelegate.progressColor != progressColor || oldDelegate.backgroundColor != backgroundColor; } }
2. 封装成可复用组件(ArcProgressBar)
把绘制器封装成一个Widget,方便在项目中直接调用:
class ArcProgressBar extends StatelessWidget { final double progress; // 0.0 到 1.0 之间的进度值 final Color progressColor; final Color backgroundColor; final double strokeWidth; final double size; // 组件的宽高 const ArcProgressBar({ super.key, required this.progress, this.progressColor = Colors.blue, this.backgroundColor = Colors.grey.shade300, this.strokeWidth = 8.0, this.size = 120.0, }); @override Widget build(BuildContext context) { return SizedBox( width: size, height: size, child: CustomPaint( painter: ArcProgressPainter( progress: progress.clamp(0.0, 1.0), // 确保进度值不会超出0-1范围 progressColor: progressColor, backgroundColor: backgroundColor, strokeWidth: strokeWidth, ), ), ); } }
3. 在页面中使用
直接调用封装好的组件即可:
// 示例:70%进度的弧形进度条 ArcProgressBar( progress: 0.7, progressColor: Colors.green, strokeWidth: 10.0, size: 150.0, )
自定义调整建议
- 如果你想改变弧形的形状,可以修改
startAngle和sweepAngle:比如把startAngle设为pi/2(90度),sweepAngle设为pi(180度),就能得到一个下半圆的弧形进度条。 - 不需要圆角端点的话,把
strokeCap改成StrokeCap.butt即可。 - 可以在组件内部添加进度文本,比如在弧形中心显示百分比,只需要在
ArcProgressBar的SizedBox里叠加一个Center组件就行。
内容的提问来源于stack exchange,提问作者user10241787
相关产品推荐
相关产品推荐

