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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:51:52