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

如何在Flutter中创建带自定义边框描边的百分比指示器

自定义环形进度指示器实现方案

既然percent_indicator包配置不够灵活,直接用Flutter自带的CustomPaint自定义实现是最靠谱的,完全能满足你图中的效果需求。

实现思路

用Stack组件堆叠三层:

  • 底层:灰色的环形背景
  • 中层:彩色的进度环(根据百分比动态绘制)
  • 顶层:中间的文字(包含标题和百分比)

完整代码示例

import 'package:flutter/material.dart';

class CustomCircularProgress extends StatelessWidget {
  final double progress; // 0-1之间的进度值
  final String title;
  final Color progressColor;
  final Color bgColor;
  final double strokeWidth;
  final double size;

  const CustomCircularProgress({
    super.key,
    required this.progress,
    required this.title,
    this.progressColor = Colors.blue,
    this.bgColor = Colors.grey,
    this.strokeWidth = 8.0,
    this.size = 120.0,
  });

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: size,
      height: size,
      child: Stack(
        alignment: Alignment.center,
        children: [
          // 环形背景
          CustomPaint(
            painter: _CircularPainter(
              progress: 1.0,
              color: bgColor,
              strokeWidth: strokeWidth,
            ),
            size: Size(size, size),
          ),
          // 进度环
          CustomPaint(
            painter: _CircularPainter(
              progress: progress,
              color: progressColor,
              strokeWidth: strokeWidth,
            ),
            size: Size(size, size),
          ),
          // 中间文字
          Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              Text(
                title,
                style: const TextStyle(
                  fontSize: 16,
                  fontWeight: FontWeight.w500,
                ),
              ),
              const SizedBox(height: 4),
              Text(
                '${(progress * 100).toInt()}%',
                style: const TextStyle(
                  fontSize: 24,
                  fontWeight: FontWeight.bold,
                ),
              ),
            ],
          ),
        ],
      ),
    );
  }
}

class _CircularPainter extends CustomPainter {
  final double progress;
  final Color color;
  final double strokeWidth;

  _CircularPainter({
    required this.progress,
    required this.color,
    required this.strokeWidth,
  });

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

    final paint = Paint()
      ..color = color
      ..strokeWidth = strokeWidth
      ..style = PaintingStyle.stroke
      ..strokeCap = StrokeCap.round; // 进度环两端圆角,和图中效果一致

    // 绘制圆弧,从顶部开始(-90度),顺时针绘制
    final arcAngle = 2 * 3.1415926 * progress;
    canvas.drawArc(
      Rect.fromCircle(center: center, radius: radius),
      -3.1415926 / 2, // 起始角度:顶部
      arcAngle,
      false,
      paint,
    );
  }

  @override
  bool shouldRepaint(covariant _CircularPainter oldDelegate) {
    return progress != oldDelegate.progress ||
        color != oldDelegate.color ||
        strokeWidth != oldDelegate.strokeWidth;
  }
}

// 使用示例
class DemoPage extends StatelessWidget {
  const DemoPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: CustomCircularProgress(
          progress: 0.75,
          title: '完成率',
          progressColor: Colors.green,
        ),
      ),
    );
  }
}

可自定义的参数

  • progress:0-1的进度值,控制进度环长度
  • title:中间的标题文字
  • progressColor:进度环颜色
  • bgColor:背景环颜色
  • strokeWidth:环形的宽度
  • size:整个组件的尺寸

你可以根据自己的需求调整这些参数,甚至扩展更多样式(比如文字颜色、字体大小、进度环的端点样式等),完全不受第三方包的限制。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 03:55:16