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

Flutter中如何用自定义Widget替代Container边框实现随子组件增长的环形进度条

实现方案

你可以通过自定义CustomPainter绘制环形进度条,再封装成通用包裹组件自动适配子组件尺寸,同时绑定进度值和尺寸变化逻辑即可。


第一步:实现环形进度条绘制类

import 'dart:math';
import 'package:flutter/material.dart';

class CircleProgressPainter extends CustomPainter {
  final double progress; // 取值范围0~1
  final double strokeWidth;
  final Color progressColor;
  final Color trackColor;

  CircleProgressPainter({
    required this.progress,
    required this.strokeWidth,
    required this.progressColor,
    required this.trackColor,
  });

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

    // 绘制环形轨道
    final trackPaint = Paint()
      ..color = trackColor
      ..style = PaintingStyle.stroke
      ..strokeWidth = strokeWidth
      ..isAntiAlias = true;
    canvas.drawCircle(center, radius, trackPaint);

    // 绘制进度弧
    final progressPaint = Paint()
      ..color = progressColor
      ..style = PaintingStyle.stroke
      ..strokeWidth = strokeWidth
      ..strokeCap = StrokeCap.round
      ..isAntiAlias = true;
    canvas.drawArc(
      Rect.fromCircle(center: center, radius: radius),
      -pi / 2, // 从顶部开始绘制
      2 * pi * progress,
      false,
      progressPaint,
    );
  }

  @override
  bool shouldRepaint(covariant CircleProgressPainter oldDelegate) {
    return progress != oldDelegate.progress ||
        strokeWidth != oldDelegate.strokeWidth ||
        progressColor != oldDelegate.progressColor ||
        trackColor != oldDelegate.trackColor;
  }
}

第二步:封装自动适配尺寸的进度包裹组件

class CircleProgressWrapper extends StatelessWidget {
  final Widget child;
  final double progress;
  final double strokeWidth;
  final Color progressColor;
  final Color trackColor;
  final Color contentBgColor;
  final double padding;
  final List<BoxShadow>? boxShadow;

  const CircleProgressWrapper({
    super.key,
    required this.child,
    required this.progress,
    required this.strokeWidth,
    required this.progressColor,
    required this.trackColor,
    required this.contentBgColor,
    this.padding = 20,
    this.boxShadow,
  });

  @override
  Widget build(BuildContext context) {
    return IntrinsicHeight(
      child: IntrinsicWidth(
        child: Stack(
          alignment: Alignment.center,
          children: [
            // 内部内容容器
            Container(
              padding: EdgeInsets.all(padding),
              decoration: BoxDecoration(
                color: contentBgColor,
                shape: BoxShape.circle,
                boxShadow: boxShadow,
              ),
              child: child,
            ),
            // 外层环形进度条
            Positioned.fill(
              child: CustomPaint(
                painter: CircleProgressPainter(
                  progress: progress,
                  strokeWidth: strokeWidth,
                  progressColor: progressColor,
                  trackColor: trackColor,
                ),
              ),
            )
          ],
        ),
      ),
    );
  }
}

第三步:替换你的原有代码

直接用封装好的组件替换原有Container即可,只要把控制子组件尺寸变化的变量和progress参数绑定,就能实现进度和尺寸同步增长的效果:

// 示例中progress为0~1的变量,和子组件尺寸变化逻辑同步更新即可
CircleProgressWrapper(
  progress: progress,
  strokeWidth: 5,
  progressColor: Colors.blue, // 替换为你的进度条颜色
  trackColor: Colors.transparent, // 如果需要轨道背景色可自行修改
  contentBgColor: context.themeCopyExtensions.backgroundColor,
  padding: 20,
  boxShadow: [
    BoxShadow(
      color: context.themeCopyExtensions.backgroundColor,
      blurRadius: 10,
    )
  ],
  child: ImagesHelper.imagesHelper.getAssetImage(imageName: "logo"),
)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.12 10:15:03